From aeebeb4eca5967d2a893ac09464499301936a134 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Tue, 13 Jun 2023 19:53:03 +0000 Subject: Use a strongly typed Pid in WindowInfo Bug: 286428012 Test: presubmit Change-Id: I6a3572ff10b259feae74863c0203bb5f085f233f --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a5d7ce7966..5a010e8af6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2453,7 +2453,7 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) { if (!hasInputInfo()) { mDrawingState.inputInfo.name = getName(); mDrawingState.inputInfo.ownerUid = gui::Uid{mOwnerUid}; - mDrawingState.inputInfo.ownerPid = mOwnerPid; + mDrawingState.inputInfo.ownerPid = gui::Pid{mOwnerPid}; mDrawingState.inputInfo.inputConfig |= WindowInfo::InputConfig::NO_INPUT_CHANNEL; mDrawingState.inputInfo.displayId = getLayerStack().id; } -- cgit v1.2.3-59-g8ed1b From 8117c1a78d49c3e02f2ece22b994ace03c200153 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 24 May 2023 15:12:15 -0700 Subject: SF: Introduce struct surfaceflinger::Config This pulls out all the individual configuration constants read by SurfaceFlinger in its constructor, and moves them to a new surfaceflinger::Config structure which is passed to the constructor. All the initialization is the functionally the same, a few values turned out to not be used, so were removed (mMaxGraphicBufferProducerListSize, mGraphicBufferProducerListSizeLogThreshold). Otherwise all properties read for the new structure consistently use android-base/properties.h to read them. To keep the argument count down, the SurfaceFlinger factory argument to the constructor was moved to be stored in the new Config structure. As a result of the change, SurfaceFlinger now only has one constructor. The tests were using the other constructor (passing SurfaceFlinger::skipInitiailization) to skip over the property reads to help ensure a hermetic configuration of SurfaceFlinger. The tests can now instead create create a minimally configured Config structure, and pass that the structure. The other changes were then to switch over to using the values in the Config structure, both internally to SurfaceFlinger, as well as in other files including Layer.cpp and DisplayDevice.cpp. In some cases, those changes required altering the arguments to the function being called to obtain the values, since originally some of the values where static member data in SurfaceFlinger. There were similar changes required for the tests and the fuzzers, to switch over, including how some tests mutated the configuration values so that they overall coverage was the same. No new tests/fuzzing was added, though it should now be easier to extend coverage. Test: atest libsurfaceflinger_unittest Bug: None Change-Id: I8dc3c2317a92b256e58ec45190e24463032c2f8e --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/DisplayDevice.cpp | 24 +- services/surfaceflinger/DisplayDevice.h | 3 +- .../DisplayHardware/FramebufferSurface.cpp | 6 +- .../DisplayHardware/FramebufferSurface.h | 2 +- .../DisplayHardware/VirtualDisplaySurface.cpp | 4 +- .../DisplayHardware/VirtualDisplaySurface.h | 3 +- services/surfaceflinger/Layer.cpp | 6 +- services/surfaceflinger/LayerRenderArea.cpp | 2 +- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 321 +++++++-------------- services/surfaceflinger/SurfaceFlinger.h | 113 +------- services/surfaceflinger/SurfaceFlingerConfig.cpp | 162 +++++++++++ services/surfaceflinger/SurfaceFlingerConfig.h | 145 ++++++++++ services/surfaceflinger/SurfaceFlingerFactory.cpp | 11 +- .../surfaceflinger_displayhardware_fuzzer.cpp | 6 +- .../fuzzer/surfaceflinger_fuzzer.cpp | 30 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 16 +- .../fuzzer/surfaceflinger_service_fuzzer.cpp | 4 +- .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../unittests/DisplayTransactionTestHelpers.h | 4 +- .../tests/unittests/SchedulerTest.cpp | 4 +- ...urfaceFlinger_GetDisplayNativePrimariesTest.cpp | 4 +- ...ceFlinger_SetupNewDisplayDeviceInternalTest.cpp | 2 +- .../tests/unittests/TestableSurfaceFlinger.h | 17 +- 25 files changed, 491 insertions(+), 403 deletions(-) create mode 100644 services/surfaceflinger/SurfaceFlingerConfig.cpp create mode 100644 services/surfaceflinger/SurfaceFlingerConfig.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 89c80bc83a..bf07f7253f 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -195,6 +195,7 @@ filegroup { "ScreenCaptureOutput.cpp", "StartPropertySetThread.cpp", "SurfaceFlinger.cpp", + "SurfaceFlingerConfig.cpp", "SurfaceFlingerDefaultFactory.cpp", "Tracing/LayerTracing.cpp", "Tracing/TransactionTracing.cpp", diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index f6ca9e2856..2789fa6bf2 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -78,18 +78,19 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) .setDisplayHeight(ANativeWindow_getHeight(args.nativeWindow.get())) .setNativeWindow(std::move(args.nativeWindow)) .setDisplaySurface(std::move(args.displaySurface)) - .setMaxTextureCacheSize( - static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)) + .setMaxTextureCacheSize(static_cast( + mFlinger->getConfig().maxFrameBufferAcquiredBuffers)) .build()); - if (!mFlinger->mDisableClientCompositionCache && - SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { + if (!mFlinger->getConfig().disableClientCompositionCache && + mFlinger->getConfig().maxFrameBufferAcquiredBuffers > 0) { mCompositionDisplay->createClientCompositionCache( - static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)); + static_cast(mFlinger->getConfig().maxFrameBufferAcquiredBuffers)); } - mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy); - mCompositionDisplay->setTreat170mAsSrgb(mFlinger->mTreat170mAsSrgb); + mCompositionDisplay->setPredictCompositionStrategy( + mFlinger->getConfig().predictCompositionStrategy); + mCompositionDisplay->setTreat170mAsSrgb(mFlinger->getConfig().treat170mAsSrgb); mCompositionDisplay->createDisplayColorProfile( compositionengine::DisplayColorProfileCreationArgsBuilder() .setHasWideColorGamut(args.hasWideColorGamut) @@ -411,23 +412,22 @@ HdrCapabilities DisplayDevice::getHdrCapabilities() const { capabilities.getDesiredMinLuminance()); } -void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, - bool showRenderRate, bool showInMiddle) { +void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc) { if (!enable) { mRefreshRateOverlay.reset(); return; } ftl::Flags features; - if (showSpinner) { + if (mFlinger->getConfig().refreshRateOverlay.showSpinner) { features |= RefreshRateOverlay::Features::Spinner; } - if (showRenderRate) { + if (mFlinger->getConfig().refreshRateOverlay.showRenderRate) { features |= RefreshRateOverlay::Features::RenderRate; } - if (showInMiddle) { + if (mFlinger->getConfig().refreshRateOverlay.showInMiddle) { features |= RefreshRateOverlay::Features::ShowInMiddle; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index dc5f8a85af..d2a9fb685a 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -236,8 +236,7 @@ public: } // Enables an overlay to be displayed with the current refresh rate - void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate, - bool showInMiddle) REQUIRES(kMainThreadContext); + void enableRefreshRateOverlay(bool enable, bool setByHwc) REQUIRES(kMainThreadContext); void updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc = false); bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; } bool onKernelTimerChanged(std::optional, bool timerExpired); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index ce602a8ad9..14fff772db 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -50,7 +50,8 @@ using ui::Dataspace; FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId, const sp& consumer, - const ui::Size& size, const ui::Size& maxSize) + const ui::Size& size, const ui::Size& maxSize, + int maxAcquiredBufferCount) : ConsumerBase(consumer), mDisplayId(displayId), mMaxSize(maxSize), @@ -70,8 +71,7 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displa GRALLOC_USAGE_HW_COMPOSER); const auto limitedSize = limitSize(size); mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height); - mConsumer->setMaxAcquiredBufferCount( - SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1); + mConsumer->setMaxAcquiredBufferCount(maxAcquiredBufferCount); for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) { mHwcBufferIds[i] = UINT64_MAX; diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 0b863daf47..5a1d14fdfe 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -42,7 +42,7 @@ class FramebufferSurface : public ConsumerBase, public compositionengine::Displa public: FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId, const sp& consumer, const ui::Size& size, - const ui::Size& maxSize); + const ui::Size& maxSize, int maxAcquiredBufferCount); virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index d62075ec65..d759c12612 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -50,7 +50,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId d const sp& sink, const sp& bqProducer, const sp& bqConsumer, - const std::string& name) + const std::string& name, bool useHwcForRgbToYuv) : ConsumerBase(bqConsumer), mHwc(hwc), mDisplayId(displayId), @@ -69,7 +69,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId d mOutputFence(Fence::NO_FENCE), mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), - mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) { + mForceHwcCopy(useHwcForRgbToYuv) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bqProducer; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index be06e2bb10..8a56d5f7b5 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -77,7 +77,8 @@ class VirtualDisplaySurface : public compositionengine::DisplaySurface, public: VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp& sink, const sp& bqProducer, - const sp& bqConsumer, const std::string& name); + const sp& bqConsumer, const std::string& name, + bool useHwcForRgbToYuv); // // DisplaySurface interface diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fabcd6168c..fd93ae219a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2562,7 +2562,7 @@ bool Layer::hasInputInfo() const { compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( const DisplayDevice* display) const { if (!display) return nullptr; - if (!mFlinger->mLayerLifecycleManagerEnabled) { + if (!mFlinger->getConfig().layerLifecycleManagerEnabled) { return display->getCompositionDisplay()->getOutputLayerForLayer( getCompositionEngineLayerFE()); } @@ -2907,7 +2907,7 @@ void Layer::onSurfaceFrameCreated( void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { - if (mFlinger->mLayerLifecycleManagerEnabled) { + if (mFlinger->getConfig().layerLifecycleManagerEnabled) { handle->transformHint = mTransformHint; } else { handle->transformHint = mSkipReportingTransformHint @@ -3162,7 +3162,7 @@ bool Layer::setBuffer(std::shared_ptr& buffer, mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(), mOwnerUid, postTime, getGameMode()); - if (mFlinger->mLegacyFrontEndEnabled) { + if (mFlinger->getConfig().legacyFrontEndEnabled) { recordLayerHistoryBufferUpdate(getLayerProps()); } diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp index 51d4ff854f..9c1944b122 100644 --- a/services/surfaceflinger/LayerRenderArea.cpp +++ b/services/surfaceflinger/LayerRenderArea.cpp @@ -78,7 +78,7 @@ void LayerRenderArea::render(std::function drawLayers) { mTransform = mLayerTransform.inverse(); } - if (mFlinger.mLayerLifecycleManagerEnabled) { + if (mFlinger.getConfig().layerLifecycleManagerEnabled) { drawLayers(); return; } diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 8f658d5a09..03f3b402c9 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -322,7 +322,7 @@ void RegionSamplingThread::captureSample() { }; std::function>>()> getLayerSnapshots; - if (mFlinger.mLayerLifecycleManagerEnabled) { + if (mFlinger.getConfig().layerLifecycleManagerEnabled) { auto filterFn = [&](const frontend::LayerSnapshot& snapshot, bool& outStopTraversal) -> bool { const Rect bounds = diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 975b54a27d..ae1b095206 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -213,16 +213,6 @@ static constexpr int FOUR_K_HEIGHT = 2160; // TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity. constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; -float getDensityFromProperty(const char* property, bool required) { - char value[PROPERTY_VALUE_MAX]; - const float density = property_get(property, value, nullptr) > 0 ? std::atof(value) : 0.f; - if (!density && required) { - ALOGE("%s must be defined as a build property", property); - return FALLBACK_DENSITY; - } - return density; -} - // Currently we only support V0_SRGB and DISPLAY_P3 as composition preference. bool validateCompositionDataspace(Dataspace dataspace) { return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3; @@ -321,18 +311,6 @@ const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB // --------------------------------------------------------------------------- -int64_t SurfaceFlinger::dispSyncPresentTimeOffset; -bool SurfaceFlinger::useHwcForRgbToYuv; -bool SurfaceFlinger::hasSyncFramework; -int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; -int64_t SurfaceFlinger::minAcquiredBuffers = 1; -uint32_t SurfaceFlinger::maxGraphicsWidth; -uint32_t SurfaceFlinger::maxGraphicsHeight; -bool SurfaceFlinger::useContextPriority; -Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB; -ui::PixelFormat SurfaceFlinger::defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888; -Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB; -ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; LatchUnsignaledConfig SurfaceFlinger::enableLatchUnsignaledConfig; std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { @@ -359,136 +337,35 @@ bool callingThreadHasPermission(const String16& permission) { ui::Transform::RotationFlags SurfaceFlinger::sActiveDisplayRotationFlags = ui::Transform::ROT_0; -SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) - : mFactory(factory), - mPid(getpid()), +SurfaceFlinger::SurfaceFlinger(surfaceflinger::Config& config) + : mConfig(&config), + mDebugFlashDelay(base::GetUintProperty("debug.sf.showupdates"s, 0u)), mTimeStats(std::make_shared()), - mFrameTracer(mFactory.createFrameTracer()), - mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)), - mCompositionEngine(mFactory.createCompositionEngine()), - mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)), + mFrameTracer(mConfig->factory->createFrameTracer()), + mFrameTimeline(mConfig->factory->createFrameTimeline(mTimeStats, mConfig->pid)), + mCompositionEngine(mConfig->factory->createCompositionEngine()), mTunnelModeEnabledReporter(sp::make()), - mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)), - mInternalDisplayDensity( - getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)), mPowerAdvisor(std::make_unique(*this)), mWindowInfosListenerInvoker(sp::make()) { - ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str()); -} - -SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { ATRACE_CALL(); - ALOGI("SurfaceFlinger is starting"); - - hasSyncFramework = running_without_sync_framework(true); - - dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0); - - useHwcForRgbToYuv = force_hwc_copy_for_virtual_displays(false); - - maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); - minAcquiredBuffers = - SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers); - - maxGraphicsWidth = std::max(max_graphics_width(0), 0); - maxGraphicsHeight = std::max(max_graphics_height(0), 0); - - mSupportsWideColor = has_wide_color_display(false); - mDefaultCompositionDataspace = - static_cast(default_composition_dataspace(Dataspace::V0_SRGB)); - mWideColorGamutCompositionDataspace = static_cast(wcg_composition_dataspace( - mSupportsWideColor ? Dataspace::DISPLAY_P3 : Dataspace::V0_SRGB)); - defaultCompositionDataspace = mDefaultCompositionDataspace; - wideColorGamutCompositionDataspace = mWideColorGamutCompositionDataspace; - defaultCompositionPixelFormat = static_cast( - default_composition_pixel_format(ui::PixelFormat::RGBA_8888)); - wideColorGamutCompositionPixelFormat = - static_cast(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888)); - - mColorSpaceAgnosticDataspace = - static_cast(color_space_agnostic_dataspace(Dataspace::UNKNOWN)); - - mLayerCachingEnabled = [] { - const bool enable = - android::sysprop::SurfaceFlingerProperties::enable_layer_caching().value_or(false); - return base::GetBoolProperty(std::string("debug.sf.enable_layer_caching"), enable); - }(); - - useContextPriority = use_context_priority(true); - - mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries(); + ALOGI("SurfaceFlinger is starting."); + ALOGI("Using HWComposer service: %s", mConfig->hwcServiceName.c_str()); + ALOGI_IF(mConfig->backpressureGpuComposition, "Enabling backpressure for GPU composition"); + ALOGI_IF(!mConfig->supportsBlur, "Disabling blur effects, they are not supported."); + ALOGI_IF(mConfig->trebleTestingOverride, "Enabling Treble testing override"); - // debugging stuff... - char value[PROPERTY_VALUE_MAX]; - - property_get("ro.build.type", value, "user"); - mIsUserBuild = strcmp(value, "user") == 0; - - mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u); - - mBackpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, true); - ALOGI_IF(mBackpressureGpuComposition, "Enabling backpressure for GPU composition"); - - property_get("ro.surface_flinger.supports_background_blur", value, "0"); - bool supportsBlurs = atoi(value); - mSupportsBlur = supportsBlurs; - ALOGI_IF(!mSupportsBlur, "Disabling blur effects, they are not supported."); - - const size_t defaultListSize = MAX_LAYERS; - auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); - mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; - mGraphicBufferProducerListSizeLogThreshold = - std::max(static_cast(0.95 * - static_cast(mMaxGraphicBufferProducerListSize)), - 1); - - property_get("debug.sf.luma_sampling", value, "1"); - mLumaSampling = atoi(value); - - property_get("debug.sf.disable_client_composition_cache", value, "0"); - mDisableClientCompositionCache = atoi(value); - - property_get("debug.sf.predict_hwc_composition_strategy", value, "1"); - mPredictCompositionStrategy = atoi(value); - - property_get("debug.sf.treat_170m_as_sRGB", value, "0"); - mTreat170mAsSrgb = atoi(value); - - mIgnoreHwcPhysicalDisplayOrientation = - base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, false); - - // We should be reading 'persist.sys.sf.color_saturation' here - // but since /data may be encrypted, we need to wait until after vold - // comes online to attempt to read the property. The property is - // instead read after the boot animation - - if (base::GetBoolProperty("debug.sf.treble_testing_override"s, false)) { + if (mConfig->trebleTestingOverride) { // Without the override SurfaceFlinger cannot connect to HIDL // services that are not listed in the manifests. Considered // deriving the setting from the set service name, but it // would be brittle if the name that's not 'default' is used // for production purposes later on. - ALOGI("Enabling Treble testing override"); android::hardware::details::setTrebleTestingOverride(true); } - // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner - mRefreshRateOverlaySpinner = property_get_bool("debug.sf.show_refresh_rate_overlay_spinner", 0); - mRefreshRateOverlayRenderRate = - property_get_bool("debug.sf.show_refresh_rate_overlay_render_rate", 0); - mRefreshRateOverlayShowInMiddle = - property_get_bool("debug.sf.show_refresh_rate_overlay_in_middle", 0); - - if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) { + if (!mConfig->isUserBuild && mConfig->enableTransactionTracing) { mTransactionTracing.emplace(); } - - mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false); - - mLayerLifecycleManagerEnabled = - base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, false); - mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled || - base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false); } LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() { @@ -815,17 +692,18 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { // Get a RenderEngine for the given display / config (can't fail) // TODO(b/77156734): We need to stop casting and use HAL types when possible. // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display. - auto builder = renderengine::RenderEngineCreationArgs::Builder() - .setPixelFormat(static_cast(defaultCompositionPixelFormat)) - .setImageCacheSize(maxFrameBufferAcquiredBuffers) - .setUseColorManagerment(useColorManagement) - .setEnableProtectedContext(enable_protected_contents(false)) - .setPrecacheToneMapperShaderOnly(false) - .setSupportsBackgroundBlur(mSupportsBlur) - .setContextPriority( - useContextPriority - ? renderengine::RenderEngine::ContextPriority::REALTIME - : renderengine::RenderEngine::ContextPriority::MEDIUM); + auto builder = + renderengine::RenderEngineCreationArgs::Builder() + .setPixelFormat(static_cast(mConfig->defaultCompositionPixelFormat)) + .setImageCacheSize(mConfig->maxFrameBufferAcquiredBuffers) + .setUseColorManagerment(useColorManagement) + .setEnableProtectedContext(enable_protected_contents(false)) + .setPrecacheToneMapperShaderOnly(false) + .setSupportsBackgroundBlur(mConfig->supportsBlur) + .setContextPriority( + mConfig->useContextPriority + ? renderengine::RenderEngine::ContextPriority::REALTIME + : renderengine::RenderEngine::ContextPriority::MEDIUM); if (auto type = chooseRenderEngineTypeViaSysProp()) { builder.setRenderEngineType(type.value()); } @@ -840,7 +718,7 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { } mCompositionEngine->setTimeStats(mTimeStats); - mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName)); + mCompositionEngine->setHwComposer(getFactory().createHWComposer(mConfig->hwcServiceName)); mCompositionEngine->getHwComposer().setCallback(*this); ClientCache::getInstance().setRenderEngine(&getRenderEngine()); @@ -1032,11 +910,11 @@ status_t SurfaceFlinger::getStaticDisplayInfo(int64_t displayId, ui::StaticDispl info->connectionType = snapshot.connectionType(); info->deviceProductInfo = snapshot.deviceProductInfo(); - if (mEmulatedDisplayDensity) { - info->density = mEmulatedDisplayDensity; + if (mConfig->emulatedDisplayDensity) { + info->density = mConfig->emulatedDisplayDensity; } else { info->density = info->connectionType == ui::DisplayConnectionType::Internal - ? mInternalDisplayDensity + ? mConfig->internalDisplayDensity : FALLBACK_DENSITY; } info->density /= ACONFIGURATION_DENSITY_MEDIUM; @@ -1099,7 +977,7 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info info->supportedDisplayModes.push_back(outMode); } - info->supportedColorModes = snapshot.filterColorModes(mSupportsWideColor); + info->supportedColorModes = snapshot.filterColorModes(mConfig->supportsWideColor); const PhysicalDisplayId displayId = snapshot.displayId(); @@ -1497,7 +1375,7 @@ status_t SurfaceFlinger::getDisplayNativePrimaries(const sp& displayTok } // TODO(b/229846990): For now, assume that all internal displays have the same primaries. - primaries = mInternalDisplayPrimaries; + primaries = mConfig->internalDisplayPrimaries; return NO_ERROR; } @@ -1521,7 +1399,7 @@ status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, ui: const auto& [display, snapshotRef] = *displayOpt; const auto& snapshot = snapshotRef.get(); - const auto modes = snapshot.filterColorModes(mSupportsWideColor); + const auto modes = snapshot.filterColorModes(mConfig->supportsWideColor); const bool exists = std::find(modes.begin(), modes.end(), mode) != modes.end(); if (mode < ui::ColorMode::NATIVE || !exists) { @@ -1827,7 +1705,7 @@ status_t SurfaceFlinger::isWideColorDisplay(const sp& displayToken, } *outIsWideColorDisplay = - display->isPrimary() ? mSupportsWideColor : display->hasWideColorGamut(); + display->isPrimary() ? mConfig->supportsWideColor : display->hasWideColorGamut(); return NO_ERROR; } @@ -1848,10 +1726,12 @@ status_t SurfaceFlinger::getCompositionPreference( Dataspace* outDataspace, ui::PixelFormat* outPixelFormat, Dataspace* outWideColorGamutDataspace, ui::PixelFormat* outWideColorGamutPixelFormat) const { - *outDataspace = mDefaultCompositionDataspace; - *outPixelFormat = defaultCompositionPixelFormat; - *outWideColorGamutDataspace = mWideColorGamutCompositionDataspace; - *outWideColorGamutPixelFormat = wideColorGamutCompositionPixelFormat; + *outDataspace = + mOverrideDefaultCompositionDataspace.value_or(mConfig->defaultCompositionDataspace); + *outPixelFormat = mConfig->defaultCompositionPixelFormat; + *outWideColorGamutDataspace = mOverrideWideColorGamutCompositionDataspace.value_or( + mConfig->wideColorGamutCompositionDataspace); + *outWideColorGamutPixelFormat = mConfig->wideColorGamutCompositionPixelFormat; return NO_ERROR; } @@ -2259,7 +2139,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, frontend::Update& upd .displays = mFrontEndDisplayInfos, .displayChanges = mFrontEndDisplayInfosChanged, .globalShadowSettings = mDrawingState.globalShadowSettings, - .supportsBlur = mSupportsBlur, + .supportsBlur = mConfig->supportsBlur, .forceFullDamage = mForceFullDamage, .supportedLayerGenericMetadata = getHwComposer().getSupportedLayerGenericMetadata(), @@ -2279,7 +2159,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, frontend::Update& upd mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0; bool newDataLatched = false; - if (!mLegacyFrontEndEnabled) { + if (!mConfig->legacyFrontEndEnabled) { ATRACE_NAME("DisplayCallbackAndStatsUpdates"); applyTransactions(update.transactions, vsyncId); const nsecs_t latchTime = systemTime(); @@ -2373,7 +2253,7 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) } if (pacesetterFrameTarget.isFramePending()) { - if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) { + if (mConfig->backpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) { scheduleCommit(FrameHint::kNone); return false; } @@ -2404,7 +2284,7 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod); } - if (mRefreshRateOverlaySpinner) { + if (mConfig->refreshRateOverlay.showSpinner) { Mutex::Autolock lock(mStateLock); if (const auto display = getDefaultDisplayDeviceLocked()) { display->animateRefreshRateOverlay(); @@ -2431,11 +2311,11 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) } } bool transactionsAreEmpty; - if (mLegacyFrontEndEnabled) { + if (mConfig->legacyFrontEndEnabled) { mustComposite |= updateLayerSnapshotsLegacy(vsyncId, updates, flushTransactions, transactionsAreEmpty); } - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { mustComposite |= updateLayerSnapshots(vsyncId, updates, flushTransactions, transactionsAreEmpty); } @@ -2539,7 +2419,7 @@ CompositeResult SurfaceFlinger::composite(scheduler::FrameTargeter& pacesetterFr refreshArgs.outputColorSetting = useColorManagement ? mDisplayColorSetting : compositionengine::OutputColorSetting::kUnmanaged; - refreshArgs.colorSpaceAgnosticDataspace = mColorSpaceAgnosticDataspace; + refreshArgs.colorSpaceAgnosticDataspace = mConfig->colorSpaceAgnosticDataspace; refreshArgs.forceOutputColorMode = mForceColorMode; refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty; @@ -2693,7 +2573,7 @@ bool SurfaceFlinger::isHdrLayer(const frontend::LayerSnapshot& snapshot) const { // Even though the camera layer may be using an HDR transfer function or otherwise be "HDR" // the device may need to avoid boosting the brightness as a result of these layers to // reduce power consumption during camera recording - if (mIgnoreHdrCameraLayers) { + if (mConfig->ignoreHdrCameraLayers) { if (snapshot.externalTexture && (snapshot.externalTexture->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) { return false; @@ -2724,7 +2604,7 @@ ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId, if (!id) { return ui::ROTATION_0; } - if (!mIgnoreHwcPhysicalDisplayOrientation && + if (!mConfig->ignoreHwcPhysicalDisplayOrientation && getHwComposer().getComposer()->isSupported( Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) { switch (getHwComposer().getPhysicalDisplayOrientation(*id)) { @@ -2919,7 +2799,7 @@ void SurfaceFlinger::postComposition(scheduler::FrameTargeter& pacesetterFrameTa const bool isDisplayConnected = defaultDisplay && getHwComposer().isConnected(defaultDisplay->getPhysicalId()); - if (!hasSyncFramework) { + if (!mConfig->hasSyncFramework) { if (isDisplayConnected && defaultDisplay->isPoweredOn()) { mScheduler->enableHardwareVsync(defaultDisplay->getPhysicalId()); } @@ -2960,7 +2840,7 @@ void SurfaceFlinger::postComposition(scheduler::FrameTargeter& pacesetterFrameTa if (!layer->hasTrustedPresentationListener()) { return; } - const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled + const frontend::LayerSnapshot* snapshot = mConfig->layerLifecycleManagerEnabled ? mLayerSnapshotBuilder.getSnapshot(layer->sequence) : layer->getLayerSnapshot(); std::optional displayOpt = std::nullopt; @@ -3355,7 +3235,7 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, builder.setPowerAdvisor(mPowerAdvisor.get()); builder.setName(state.displayName); auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); - compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled); + compositionDisplay->setLayerCachingEnabled(mConfig->layerCachingEnabled); sp displaySurface; sp producer; @@ -3367,7 +3247,8 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId()); LOG_FATAL_IF(!displayId); auto surface = sp::make(getHwComposer(), *displayId, state.surface, - bqProducer, bqConsumer, state.displayName); + bqProducer, bqConsumer, state.displayName, + mConfig->useHwcForRgbToYuv); displaySurface = surface; producer = std::move(surface); } else { @@ -3377,10 +3258,11 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, state.surface.get()); const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId()); LOG_FATAL_IF(!displayId); - displaySurface = - sp::make(getHwComposer(), *displayId, bqConsumer, - state.physical->activeMode->getResolution(), - ui::Size(maxGraphicsWidth, maxGraphicsHeight)); + displaySurface = sp::make(getHwComposer(), *displayId, bqConsumer, + state.physical->activeMode->getResolution(), + ui::Size(mConfig->maxGraphicsWidth, + mConfig->maxGraphicsHeight), + mConfig->maxFrameBufferAcquiredBuffers); producer = bqProducer; } @@ -3561,7 +3443,7 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { // Commit display transactions. const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded; mFrontEndDisplayInfosChanged = displayTransactionNeeded; - if (displayTransactionNeeded && !mLayerLifecycleManagerEnabled) { + if (displayTransactionNeeded && !mConfig->layerLifecycleManagerEnabled) { processDisplayChangesLocked(); mFrontEndDisplayInfos.clear(); for (const auto& [_, display] : mDisplays) { @@ -3761,7 +3643,7 @@ void SurfaceFlinger::buildWindowInfos(std::vector& outWindowInfos, outWindowInfos.reserve(sNumWindowInfos); sNumWindowInfos = 0; - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { mLayerSnapshotBuilder.forEachInputSnapshot( [&outWindowInfos](const frontend::LayerSnapshot& snapshot) { outWindowInfos.push_back(snapshot.inputInfo); @@ -3881,7 +3763,7 @@ void SurfaceFlinger::initScheduler(const sp& display) { if (display->refreshRateSelector().kernelIdleTimerController()) { features |= Feature::kKernelIdleTimer; } - if (mBackpressureGpuComposition) { + if (mConfig->backpressureGpuComposition) { features |= Feature::kBackpressureGpuComposition; } @@ -4554,7 +4436,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin const std::vector& listenerCallbacks, int originPid, int originUid, uint64_t transactionId) { uint32_t transactionFlags = 0; - if (!mLayerLifecycleManagerEnabled) { + if (!mConfig->layerLifecycleManagerEnabled) { for (DisplayState& display : displays) { transactionFlags |= setDisplayStateLocked(display); } @@ -4569,12 +4451,12 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin uint32_t clientStateFlags = 0; for (auto& resolvedState : states) { - if (mLegacyFrontEndEnabled) { + if (mConfig->legacyFrontEndEnabled) { clientStateFlags |= setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime, isAutoTimestamp, postTime, transactionId); - } else /*mLayerLifecycleManagerEnabled*/ { + } else /* mConfig->layerLifecycleManagerEnabled */ { clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, desiredPresentTime, isAutoTimestamp, postTime, transactionId); @@ -4648,7 +4530,7 @@ bool SurfaceFlinger::applyAndCommitDisplayTransactionStates( } mFrontEndDisplayInfosChanged = mTransactionFlags & eDisplayTransactionNeeded; - if (mFrontEndDisplayInfosChanged && !mLegacyFrontEndEnabled) { + if (mFrontEndDisplayInfosChanged && !mConfig->legacyFrontEndEnabled) { processDisplayChangesLocked(); mFrontEndDisplayInfos.clear(); for (const auto& [_, display] : mDisplays) { @@ -4851,7 +4733,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime if (layer->setCornerRadius(s.cornerRadius)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eBackgroundBlurRadiusChanged && mSupportsBlur) { + if (what & layer_state_t::eBackgroundBlurRadiusChanged && mConfig->supportsBlur) { if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded; } if (what & layer_state_t::eBlurRegionsChanged) { @@ -5255,7 +5137,7 @@ status_t SurfaceFlinger::mirrorDisplay(DisplayId displayId, const LayerCreationA return result; } - if (mLegacyFrontEndEnabled) { + if (mConfig->legacyFrontEndEnabled) { std::scoped_lock lock(mMirrorDisplayLock); mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client); } @@ -5362,9 +5244,10 @@ void SurfaceFlinger::initializeDisplays() { const nsecs_t now = systemTime(); state.desiredPresentTime = now; state.postTime = now; - state.originPid = mPid; + state.originPid = mConfig->pid; state.originUid = static_cast(getuid()); - const uint64_t transactionId = (static_cast(mPid) << 32) | mUniqueTransactionId++; + const uint64_t transactionId = + (static_cast(mConfig->pid) << 32) | mUniqueTransactionId++; state.id = transactionId; // reset screen orientation and use primary layer stack @@ -5384,7 +5267,7 @@ void SurfaceFlinger::initializeDisplays() { std::vector transactions; transactions.emplace_back(state); - if (mLegacyFrontEndEnabled) { + if (mConfig->legacyFrontEndEnabled) { applyTransactions(transactions, VsyncId{0}); } else { applyAndCommitDisplayTransactionStates(transactions); @@ -5680,13 +5563,13 @@ void SurfaceFlinger::logFrameStats(TimePoint now) { void SurfaceFlinger::appendSfConfigString(std::string& result) const { result.append(" [sf"); - StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset); - StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv); + StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, mConfig->dispSyncPresentTimeOffset); + StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", mConfig->useHwcForRgbToYuv); StringAppendF(&result, " MAX_VIRT_DISPLAY_DIM=%zu", getHwComposer().getMaxVirtualDisplayDimension()); - StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework); + StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !mConfig->hasSyncFramework); StringAppendF(&result, " NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64, - maxFrameBufferAcquiredBuffers); + mConfig->maxFrameBufferAcquiredBuffers); result.append("]"); } @@ -5706,7 +5589,7 @@ void SurfaceFlinger::dumpScheduler(std::string& result) const { StringAppendF(&result, " present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n", - dispSyncPresentTimeOffset, getVsyncPeriodFromHWC()); + mConfig->dispSyncPresentTimeOffset, getVsyncPeriodFromHWC()); } void SurfaceFlinger::dumpEvents(std::string& result) const { @@ -5805,7 +5688,7 @@ void SurfaceFlinger::dumpRawDisplayIdentificationData(const DumpArgs& args, } void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { - StringAppendF(&result, "Device supports wide color: %d\n", mSupportsWideColor); + StringAppendF(&result, "Device supports wide color: %d\n", mConfig->supportsWideColor); StringAppendF(&result, "Device uses color management: %d\n", useColorManagement); StringAppendF(&result, "DisplayColorSetting: %s\n", decodeDisplayColorSetting(mDisplayColorSetting).c_str()); @@ -5839,7 +5722,7 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } } - if (mLegacyFrontEndEnabled) { + if (mConfig->legacyFrontEndEnabled) { LayersProto layersProto; for (const sp& layer : mDrawingState.layersSortedByZ) { if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { @@ -6496,7 +6379,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r if (!validateCompositionDataspace(dataspace)) { return BAD_VALUE; } - mDefaultCompositionDataspace = dataspace; + mOverrideDefaultCompositionDataspace = dataspace; } n = data.readInt32(); if (n) { @@ -6504,12 +6387,12 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r if (!validateCompositionDataspace(dataspace)) { return BAD_VALUE; } - mWideColorGamutCompositionDataspace = dataspace; + mOverrideWideColorGamutCompositionDataspace = dataspace; } } else { - // restore composition data space. - mDefaultCompositionDataspace = defaultCompositionDataspace; - mWideColorGamutCompositionDataspace = wideColorGamutCompositionDataspace; + // Reset data space overrides. + mOverrideDefaultCompositionDataspace.reset(); + mOverrideWideColorGamutCompositionDataspace.reset(); } return NO_ERROR; } @@ -6648,10 +6531,10 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } { Mutex::Autolock lock(mStateLock); - mLayerCachingEnabled = n != 0; + mConfig->layerCachingEnabled = n != 0; for (const auto& [_, display] : mDisplays) { if (!inputId || *inputId == display->getPhysicalId()) { - display->enableLayerCaching(mLayerCachingEnabled); + display->enableLayerCaching(mConfig->layerCachingEnabled); } } } @@ -6976,7 +6859,7 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, }); GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); } else { @@ -7019,7 +6902,7 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, }); GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, /*snapshotFilterFn=*/nullptr); } else { @@ -7115,7 +6998,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr { ui::Transform layerTransform; Rect layerBufferSize; - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { frontend::LayerSnapshot* snapshot = mLayerSnapshotBuilder.getSnapshot(parent->getSequence()); if (!snapshot) { @@ -7135,7 +7018,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, args.hintForSeamlessTransition); }); GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { std::optional parentCrop = std::nullopt; if (args.childrenOnly) { parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height) @@ -7388,7 +7271,7 @@ ftl::SharedFuture SurfaceFlinger::renderScreenImpl( layerStack, regionSampling, renderArea = std::move(renderArea), renderIntent]() -> FenceResult { std::unique_ptr compositionEngine = - mFactory.createCompositionEngine(); + mConfig->factory->createCompositionEngine(); compositionEngine->setRenderEngine(mRenderEngine.get()); compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace, @@ -7458,7 +7341,7 @@ ftl::SharedFuture SurfaceFlinger::renderScreenImpl( } void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const { - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { for (auto& layer : mLegacyLayers) { visitor(layer.second.get()); } @@ -7780,9 +7663,7 @@ void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { } if (const auto device = getDisplayDeviceLocked(id)) { - device->enableRefreshRateOverlay(enable, setByHwc, mRefreshRateOverlaySpinner, - mRefreshRateOverlayRenderRate, - mRefreshRateOverlayShowInMiddle); + device->enableRefreshRateOverlay(enable, setByHwc); } } } @@ -7793,12 +7674,12 @@ int SurfaceFlinger::getGpuContextPriority() { } int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate, - std::chrono::nanoseconds presentLatency) { + std::chrono::nanoseconds presentLatency) const { auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); if (presentLatency.count() % refreshRate.getPeriodNsecs()) { pipelineDepth++; } - return std::max(minAcquiredBuffers, static_cast(pipelineDepth - 1)); + return std::max(mConfig->minAcquiredBuffers, static_cast(pipelineDepth - 1)); } status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const { @@ -7880,7 +7761,7 @@ void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state, Vs } void SurfaceFlinger::sample() { - if (!mLumaSampling || !mRegionSamplingThread) { + if (!mConfig->lumaSampling || !mRegionSamplingThread) { return; } @@ -8072,7 +7953,7 @@ void SurfaceFlinger::updateLayerMetadataSnapshot() { void SurfaceFlinger::moveSnapshotsFromCompositionArgs( compositionengine::CompositionRefreshArgs& refreshArgs, const std::vector>& layers) { - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { std::vector>& snapshots = mLayerSnapshotBuilder.getSnapshots(); for (auto [_, layerFE] : layers) { @@ -8080,7 +7961,7 @@ void SurfaceFlinger::moveSnapshotsFromCompositionArgs( snapshots[i] = std::move(layerFE->mSnapshot); } } - if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) { + if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) { for (auto [layer, layerFE] : layers) { layer->updateLayerSnapshot(std::move(layerFE->mSnapshot)); } @@ -8090,7 +7971,7 @@ void SurfaceFlinger::moveSnapshotsFromCompositionArgs( std::vector> SurfaceFlinger::moveSnapshotsToCompositionArgs( compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly) { std::vector> layers; - if (mLayerLifecycleManagerEnabled) { + if (mConfig->layerLifecycleManagerEnabled) { nsecs_t currentTime = systemTime(); mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr& snapshot) { @@ -8116,7 +7997,7 @@ std::vector> SurfaceFlinger::moveSnapshotsToComposit layers.emplace_back(legacyLayer.get(), layerFE.get()); }); } - if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) { + if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) { auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) { if (const auto& layerFE = layer->getCompositionEngineLayerFE()) { if (cursorOnly && @@ -8208,7 +8089,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(std::optional la .displays = mFrontEndDisplayInfos, .displayChanges = true, .globalShadowSettings = mDrawingState.globalShadowSettings, - .supportsBlur = mSupportsBlur, + .supportsBlur = mConfig->supportsBlur, .forceFullDamage = mForceFullDamage, .excludeLayerIds = std::move(excludeLayerIds), .supportedLayerGenericMetadata = @@ -8242,7 +8123,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t u .displays = mFrontEndDisplayInfos, .displayChanges = true, .globalShadowSettings = mDrawingState.globalShadowSettings, - .supportsBlur = mSupportsBlur, + .supportsBlur = mConfig->supportsBlur, .forceFullDamage = mForceFullDamage, .parentCrop = parentCrop, .excludeLayerIds = std::move(excludeLayerIds), diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index fd050167f7..31df2dfa43 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -63,6 +63,7 @@ #include #include +#include "Client.h" #include "Display/PhysicalDisplay.h" #include "DisplayDevice.h" #include "DisplayHardware/HWC2.h" @@ -81,6 +82,7 @@ #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateStats.h" #include "Scheduler/Scheduler.h" +#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerFactory.h" #include "ThreadContext.h" #include "Tracing/LayerTracing.h" @@ -107,7 +109,6 @@ #include #include -#include "Client.h" using namespace android::surfaceflinger; @@ -196,10 +197,7 @@ class SurfaceFlinger : public BnSurfaceComposer, private ICompositor, private scheduler::ISchedulerCallback { public: - struct SkipInitializationTag {}; - - SurfaceFlinger(surfaceflinger::Factory&, SkipInitializationTag) ANDROID_API; - explicit SurfaceFlinger(surfaceflinger::Factory&) ANDROID_API; + explicit SurfaceFlinger(surfaceflinger::Config&) ANDROID_API; // set main thread scheduling policy static status_t setSchedFifo(bool enabled) ANDROID_API; @@ -209,51 +207,9 @@ public: static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } - // If fences from sync Framework are supported. - static bool hasSyncFramework; - - // The offset in nanoseconds to use when VsyncController timestamps present fence - // signaling time. - static int64_t dispSyncPresentTimeOffset; - - // Some hardware can do RGB->YUV conversion more efficiently in hardware - // controlled by HWC than in hardware controlled by the video encoder. - // This instruct VirtualDisplaySurface to use HWC for such conversion on - // GL composition. - static bool useHwcForRgbToYuv; - - // Controls the number of buffers SurfaceFlinger will allocate for use in - // FramebufferSurface - static int64_t maxFrameBufferAcquiredBuffers; - - // Controls the minimum acquired buffers SurfaceFlinger will suggest via - // ISurfaceComposer.getMaxAcquiredBufferCount(). - static int64_t minAcquiredBuffers; - - // Controls the maximum width and height in pixels that the graphics pipeline can support for - // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs. - static uint32_t maxGraphicsWidth; - static uint32_t maxGraphicsHeight; - // Indicate if device wants color management on its display. static const constexpr bool useColorManagement = true; - static bool useContextPriority; - - // The data space and pixel format that SurfaceFlinger expects hardware composer - // to composite efficiently. Meaning under most scenarios, hardware composer - // will accept layers with the data space and pixel format. - static ui::Dataspace defaultCompositionDataspace; - static ui::PixelFormat defaultCompositionPixelFormat; - - // The data space and pixel format that SurfaceFlinger expects hardware composer - // to composite efficiently for wide color gamut surfaces. Meaning under most scenarios, - // hardware composer will accept layers with the data space and pixel format. - static ui::Dataspace wideColorGamutCompositionDataspace; - static ui::PixelFormat wideColorGamutCompositionPixelFormat; - - static constexpr SkipInitializationTag SkipInitialization; - static LatchUnsignaledConfig enableLatchUnsignaledConfig; // must be called before clients can connect @@ -274,7 +230,8 @@ public: // Schedule sampling independently from commit or composite. void scheduleSample(); - surfaceflinger::Factory& getFactory() { return mFactory; } + const surfaceflinger::Config& getConfig() { return *mConfig; } + surfaceflinger::Factory& getFactory() { return *mConfig->factory; } // The CompositionEngine encapsulates all composition related interfaces and actions. compositionengine::CompositionEngine& getCompositionEngine() const; @@ -306,10 +263,6 @@ public: return mTransactionCallbackInvoker; } - // If set, disables reusing client composition buffers. This can be set by - // debug.sf.disable_client_composition_cache - bool mDisableClientCompositionCache = false; - // Disables expensive rendering for all displays // This is scheduled on the main thread void disableExpensiveRendering(); @@ -320,17 +273,6 @@ public: // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect. bool mPredictCompositionStrategy = false; - // If true, then any layer with a SMPTE 170M transfer function is decoded using the sRGB - // transfer instead. This is mainly to preserve legacy behavior, where implementations treated - // SMPTE 170M as sRGB prior to color management being implemented, and now implementations rely - // on this behavior to increase contrast for some media sources. - bool mTreat170mAsSrgb = false; - - // Allows to ignore physical orientation provided through hwc API in favour of - // 'ro.surface_flinger.primary_display_orientation'. - // TODO(b/246793311): Clean up a temporary property - bool mIgnoreHwcPhysicalDisplayOrientation = false; - void forceFutureUpdate(int delayInMs); const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack) REQUIRES(mStateLock, kMainThreadContext); @@ -662,12 +604,6 @@ private: // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to // make calls to sys prop each time. bool mKernelIdleTimerEnabled = false; - // Show spinner with refresh rate overlay - bool mRefreshRateOverlaySpinner = false; - // Show render rate with refresh rate overlay - bool mRefreshRateOverlayRenderRate = false; - // Show render rate overlay offseted to the middle of the screen (e.g. for circular displays) - bool mRefreshRateOverlayShowInMiddle = false; void setDesiredActiveMode(display::DisplayModeRequest&&, bool force = false) REQUIRES(mStateLock); @@ -1101,8 +1037,8 @@ private: */ const std::unordered_map& getGenericLayerMetadataKeyMap() const; - static int calculateMaxAcquiredBufferCount(Fps refreshRate, - std::chrono::nanoseconds presentLatency); + int calculateMaxAcquiredBufferCount(Fps refreshRate, + std::chrono::nanoseconds presentLatency) const; int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const; bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const; @@ -1112,8 +1048,7 @@ private: void traverseLegacyLayers(const LayerVector::Visitor& visitor) const; sp mStartPropertySetThread; - surfaceflinger::Factory& mFactory; - pid_t mPid; + surfaceflinger::Config* const mConfig = nullptr; std::future mRenderEnginePrimeCacheFuture; // mStateLock has conventions related to the current thread, because only @@ -1140,12 +1075,6 @@ private: float mGlobalSaturationFactor = 1.0f; mat4 mClientColorMatrix; - size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS; - // If there are more GraphicBufferProducers tracked by SurfaceFlinger than - // this threshold, then begin logging. - size_t mGraphicBufferProducerListSizeLogThreshold = - static_cast(0.95 * static_cast(MAX_LAYERS)); - // protected by mStateLock (but we could use another lock) bool mLayersRemoved = false; bool mLayersAdded = false; @@ -1155,7 +1084,6 @@ private: // constant members (no synchronization needed for access) const nsecs_t mBootTime = systemTime(); - bool mIsUserBuild = true; // Can only accessed from the main thread, these members // don't need synchronization @@ -1167,7 +1095,6 @@ private: // Used to ensure we omit a callback when HDR layer info listener is newly added but the // scene hasn't changed bool mAddingHDRLayerInfoListener = false; - bool mIgnoreHdrCameraLayers = false; // Set during transaction application stage to track if the input info or children // for a layer has changed. @@ -1226,9 +1153,6 @@ private: std::atomic mDebugInTransaction = 0; std::atomic_bool mForceFullDamage = false; - bool mLayerCachingEnabled = false; - bool mBackpressureGpuComposition = false; - LayerTracing mLayerTracing; bool mLayerTracingEnabled = false; @@ -1241,9 +1165,6 @@ private: VsyncId mLastCommittedVsyncId; - // If blurs should be enabled on this device. - bool mSupportsBlur = false; - TransactionCallbackInvoker mTransactionCallbackInvoker; // We maintain a pool of pre-generated texture names to hand out to avoid @@ -1275,13 +1196,9 @@ private: // This property can be used to force SurfaceFlinger to always pick a certain color mode. ui::ColorMode mForceColorMode = ui::ColorMode::NATIVE; - // Whether to enable wide color gamut (e.g. Display P3) for internal displays that support it. - // If false, wide color modes are filtered out for all internal displays. - bool mSupportsWideColor = false; + std::optional mOverrideDefaultCompositionDataspace; + std::optional mOverrideWideColorGamutCompositionDataspace; - ui::Dataspace mDefaultCompositionDataspace; - ui::Dataspace mWideColorGamutCompositionDataspace; - ui::Dataspace mColorSpaceAgnosticDataspace; float mDimmingRatio = -1.f; std::unique_ptr mRenderEngine; @@ -1295,8 +1212,6 @@ private: // any mutex. size_t mMaxRenderTargetSize{1}; - const std::string mHwcServiceName; - /* * Scheduler */ @@ -1313,14 +1228,9 @@ private: // below flags are set by main thread only bool mSetActiveModePending = false; - bool mLumaSampling = true; sp mRegionSamplingThread; sp mFpsReporter; sp mTunnelModeEnabledReporter; - ui::DisplayPrimaries mInternalDisplayPrimaries; - - const float mEmulatedDisplayDensity; - const float mInternalDisplayDensity; // Should only be accessed by the main thread. sp mInputFlinger; @@ -1397,9 +1307,6 @@ private: bool mPowerHintSessionEnabled; - bool mLayerLifecycleManagerEnabled = false; - bool mLegacyFrontEndEnabled = true; - frontend::LayerLifecycleManager mLayerLifecycleManager; frontend::LayerHierarchyBuilder mLayerHierarchyBuilder{{}}; frontend::LayerSnapshotBuilder mLayerSnapshotBuilder; diff --git a/services/surfaceflinger/SurfaceFlingerConfig.cpp b/services/surfaceflinger/SurfaceFlingerConfig.cpp new file mode 100644 index 0000000000..0b25a4462d --- /dev/null +++ b/services/surfaceflinger/SurfaceFlingerConfig.cpp @@ -0,0 +1,162 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include +#include + +#include "SurfaceFlingerConfig.h" + +namespace android::surfaceflinger { + +using namespace std::string_literals; + +namespace { + +// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity. +constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; + +float getDensityFromProperty(const std::string& key, bool required) { + std::string value = base::GetProperty(key, ""s); + const float density = static_cast(std::atof(value.c_str())); + if (density == 0.f && required) { + ALOGE("%s must be defined as a build property", key.c_str()); + return FALLBACK_DENSITY; + } + return density; +} + +} // namespace + +Config::Config() = default; + +Config Config::makeDefault(Factory* factory) { + Config cfg{}; + + // Note: The values set here will affect tests. + // To keep tests hermetic, do not set values here based on runtime values. + + cfg.factory = factory; + cfg.hwcServiceName = "default"s; + cfg.pid = getpid(); // Exception to the hermetic rules. Allow the pid to be cached. + + return cfg; +} + +Config Config::makeProduction(Factory* factory) { + Config cfg = makeDefault(factory); + + cfg.hwcServiceName = base::GetProperty("debug.sf.hwc_service_name"s, "default"s); + + cfg.emulatedDisplayDensity = getDensityFromProperty("qemu.sf.lcd_density"s, false), + cfg.internalDisplayDensity = + getDensityFromProperty("ro.sf.lcd_density"s, cfg.emulatedDisplayDensity == 0.f), + + cfg.hasSyncFramework = sysprop::running_without_sync_framework(cfg.hasSyncFramework); + cfg.dispSyncPresentTimeOffset = + sysprop::present_time_offset_from_vsync_ns(cfg.dispSyncPresentTimeOffset); + cfg.useHwcForRgbToYuv = sysprop::force_hwc_copy_for_virtual_displays(cfg.useHwcForRgbToYuv); + cfg.maxFrameBufferAcquiredBuffers = + sysprop::max_frame_buffer_acquired_buffers(cfg.maxFrameBufferAcquiredBuffers); + cfg.minAcquiredBuffers = sysprop::SurfaceFlingerProperties::min_acquired_buffers().value_or( + cfg.minAcquiredBuffers); + + cfg.maxGraphicsWidth = std::max(static_cast(sysprop::max_graphics_width( + static_cast(cfg.maxGraphicsWidth))), + 0u); + cfg.maxGraphicsHeight = std::max(static_cast(sysprop::max_graphics_height( + static_cast(cfg.maxGraphicsHeight))), + 0u); + + cfg.supportsWideColor = sysprop::has_wide_color_display(cfg.supportsWideColor); + + cfg.defaultCompositionDataspace = static_cast( + sysprop::default_composition_dataspace(cfg.defaultCompositionDataspace)); + cfg.defaultCompositionPixelFormat = static_cast( + sysprop::default_composition_pixel_format(cfg.defaultCompositionPixelFormat)); + + cfg.wideColorGamutCompositionDataspace = + static_cast(sysprop::wcg_composition_dataspace( + cfg.supportsWideColor ? ui::Dataspace::DISPLAY_P3 : ui::Dataspace::V0_SRGB)); + cfg.wideColorGamutCompositionPixelFormat = static_cast( + sysprop::wcg_composition_pixel_format(cfg.wideColorGamutCompositionPixelFormat)); + + cfg.colorSpaceAgnosticDataspace = static_cast( + sysprop::color_space_agnostic_dataspace(cfg.colorSpaceAgnosticDataspace)); + + cfg.internalDisplayPrimaries = sysprop::getDisplayNativePrimaries(); + + cfg.layerCachingEnabled = + base::GetBoolProperty("debug.sf.enable_layer_caching"s, + android::sysprop::SurfaceFlingerProperties::enable_layer_caching() + .value_or(cfg.layerCachingEnabled)); + cfg.useContextPriority = sysprop::use_context_priority(cfg.useContextPriority); + + cfg.isUserBuild = "user"s == base::GetProperty("ro.build.type"s, "user"s); + + cfg.backpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, + cfg.backpressureGpuComposition); + cfg.supportsBlur = + base::GetBoolProperty("ro.surface_flinger.supports_background_blur"s, cfg.supportsBlur); + + cfg.lumaSampling = base::GetBoolProperty("debug.sf.luma_sampling"s, cfg.lumaSampling); + + cfg.disableClientCompositionCache = + base::GetBoolProperty("debug.sf.disable_client_composition_cache"s, + cfg.disableClientCompositionCache); + + cfg.predictCompositionStrategy = + base::GetBoolProperty("debug.sf.predict_hwc_composition_strategy"s, + cfg.predictCompositionStrategy); + + cfg.treat170mAsSrgb = + base::GetBoolProperty("debug.sf.treat_170m_as_sRGB"s, cfg.treat170mAsSrgb); + + cfg.ignoreHwcPhysicalDisplayOrientation = + base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, + cfg.ignoreHwcPhysicalDisplayOrientation); + + cfg.trebleTestingOverride = + base::GetBoolProperty("debug.sf.treble_testing_override"s, cfg.trebleTestingOverride); + + // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner + cfg.refreshRateOverlay.showSpinner = + base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_spinner"s, + cfg.refreshRateOverlay.showSpinner); + cfg.refreshRateOverlay.showRenderRate = + base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_render_rate"s, + cfg.refreshRateOverlay.showRenderRate); + cfg.refreshRateOverlay.showInMiddle = + base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_in_middle"s, + cfg.refreshRateOverlay.showInMiddle); + + cfg.ignoreHdrCameraLayers = sysprop::ignore_hdr_camera_layers(cfg.ignoreHdrCameraLayers); + + cfg.enableTransactionTracing = base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, + cfg.enableTransactionTracing); + cfg.layerLifecycleManagerEnabled = + base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, + cfg.layerLifecycleManagerEnabled); + cfg.legacyFrontEndEnabled = !cfg.layerLifecycleManagerEnabled || + base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false); + + return cfg; +} + +} // namespace android::surfaceflinger \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlingerConfig.h b/services/surfaceflinger/SurfaceFlingerConfig.h new file mode 100644 index 0000000000..7c3348e3bd --- /dev/null +++ b/services/surfaceflinger/SurfaceFlingerConfig.h @@ -0,0 +1,145 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +namespace android::surfaceflinger { + +class Factory; + +struct Config final { + Factory* factory = nullptr; + + std::string hwcServiceName; + pid_t pid; + + float emulatedDisplayDensity = 0; + float internalDisplayDensity = 0; + + // If fences from sync Framework are supported. + bool hasSyncFramework = true; + + // The offset in nanoseconds to use when VsyncController timestamps present + // fence signaling time. + int64_t dispSyncPresentTimeOffset = 0; + + // Some hardware can do RGB->YUV conversion more efficiently in hardware + // controlled by HWC than in hardware controlled by the video encoder. This + // instruct VirtualDisplaySurface to use HWC for such conversion on GL + // composition. + bool useHwcForRgbToYuv = false; + + // Controls the number of buffers SurfaceFlinger will allocate for use in + // FramebufferSurface + int64_t maxFrameBufferAcquiredBuffers = 2; + + // Controls the minimum acquired buffers SurfaceFlinger will suggest via + // ISurfaceComposer.getMaxAcquiredBufferCount(). + int64_t minAcquiredBuffers = 1; + + // Controls the maximum width and height in pixels that the graphics + // pipeline can support for GPU fallback composition. For example, 8k + // devices with 4k GPUs, or 4k devices with 2k GPUs. + uint32_t maxGraphicsWidth = 0; + uint32_t maxGraphicsHeight = 0; + + // Whether to enable wide color gamut (e.g. Display P3) for internal + // displays that support it. If false, wide color modes are filtered out + // for all internal displays. + bool mSupportsWideColor = false; + bool supportsWideColor = false; + + // The data space and pixel format that SurfaceFlinger expects hardware + // composer to composite efficiently. Meaning under most scenarios, + // hardware composer will accept layers with the data space and pixel + // format. + ui::Dataspace defaultCompositionDataspace = ui::Dataspace::V0_SRGB; + ui::PixelFormat defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888; + + // The data space and pixel format that SurfaceFlinger expects hardware + // composer to composite efficiently for wide color gamut surfaces. Meaning + // under most scenarios, hardware composer will accept layers with the data + // space and pixel format. + ui::Dataspace wideColorGamutCompositionDataspace = ui::Dataspace::V0_SRGB; + ui::PixelFormat wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; + + ui::Dataspace colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN; + + ui::DisplayPrimaries internalDisplayPrimaries{}; + + bool layerCachingEnabled = false; + bool useContextPriority = true; + bool isUserBuild = true; + bool backpressureGpuComposition = true; + + // If blurs should be enabled on this device. + bool supportsBlur = false; + bool lumaSampling = true; + + // If set, disables reusing client composition buffers. This can be set by + // debug.sf.disable_client_composition_cache + bool disableClientCompositionCache = false; + + // If set, composition engine tries to predict the composition strategy + // provided by HWC based on the previous frame. If the strategy can be + // predicted, gpu composition will run parallel to the hwc validateDisplay + // call and re-run if the predition is incorrect. + bool predictCompositionStrategy = true; + + // If true, then any layer with a SMPTE 170M transfer function is decoded + // using the sRGB transfer instead. This is mainly to preserve legacy + // behavior, where implementations treated SMPTE 170M as sRGB prior to + // color management being implemented, and now implementations rely on this + // behavior to increase contrast for some media sources. + bool treat170mAsSrgb = false; + + // Allows to ignore physical orientation provided through hwc API in favour + // of 'ro.surface_flinger.primary_display_orientation'. + // TODO(b/246793311): Clean up a temporary property + bool ignoreHwcPhysicalDisplayOrientation = false; + + bool trebleTestingOverride = false; + + struct { + // Show spinner with refresh rate overlay + bool showSpinner = false; + + // Show render rate with refresh rate overlay + bool showRenderRate = false; + + // Show render rate overlay offseted to the middle of the screen (e.g. + // for circular displays) + bool showInMiddle = false; + } refreshRateOverlay; + + bool ignoreHdrCameraLayers = false; + bool enableTransactionTracing = true; + bool layerLifecycleManagerEnabled = false; + bool legacyFrontEndEnabled = true; + + static Config makeDefault(Factory* factory); + static Config makeProduction(Factory* factory); + +private: + Config(); +}; + +} // namespace android::surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp index 7bd6cf69f3..ac351cb1d7 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp @@ -14,22 +14,17 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" - #include "SurfaceFlinger.h" +#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerDefaultFactory.h" namespace android::surfaceflinger { sp createSurfaceFlinger() { static DefaultFactory factory; + static Config config = Config::makeProduction(&factory); - return sp::make(factory); + return sp::make(config); } } // namespace android::surfaceflinger - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp index 9fac14ed4c..d296c47237 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp @@ -481,7 +481,8 @@ void DisplayHardwareFuzzer::invokeFrameBufferSurface() { sp surface = sp::make(mHwc, mPhysicalDisplayId, bqConsumer, - getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/); + getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/, + mFdp.PickValueInArray(kMaxFrameBufferAcquiredBuffers)); surface->beginFrame(mFdp.ConsumeBool()); surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes)); @@ -515,7 +516,8 @@ void DisplayHardwareFuzzer::invokeVirtualDisplaySurface() { auto surface = sp::make(mHwc, VirtualDisplayId, sink, bqProducer, bqConsumer, - mFdp.ConsumeRandomLengthString().c_str() /*name*/); + mFdp.ConsumeRandomLengthString().c_str() /*name*/, + mFdp.ConsumeBool() /* useHwcForRgbToYuv */); surface->beginFrame(mFdp.ConsumeBool()); surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes)); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp index 80943b5b63..df342dcd8e 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp @@ -124,19 +124,20 @@ void SurfaceFlingerFuzzer::invokeFlinger() { mFlinger->setSchedFifo(mFdp.ConsumeBool()); mFlinger->setSchedAttr(mFdp.ConsumeBool()); mFlinger->getServiceName(); - mFlinger->hasSyncFramework = mFdp.ConsumeBool(); - mFlinger->dispSyncPresentTimeOffset = mFdp.ConsumeIntegral(); - mFlinger->useHwcForRgbToYuv = mFdp.ConsumeBool(); - mFlinger->maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral(); - mFlinger->maxGraphicsWidth = mFdp.ConsumeIntegral(); - mFlinger->maxGraphicsHeight = mFdp.ConsumeIntegral(); - mTestableFlinger.mutableSupportsWideColor() = mFdp.ConsumeBool(); - mFlinger->useContextPriority = mFdp.ConsumeBool(); - - mFlinger->defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces); - mFlinger->defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); - mFlinger->wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces); - mFlinger->wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); + + auto& config = mTestableFlinger.mutableConfig(); + config.hasSyncFramework = mFdp.ConsumeBool(); + config.dispSyncPresentTimeOffset = mFdp.ConsumeIntegral(); + config.useHwcForRgbToYuv = mFdp.ConsumeBool(); + config.maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral(); + config.maxGraphicsWidth = mFdp.ConsumeIntegral(); + config.maxGraphicsHeight = mFdp.ConsumeIntegral(); + config.supportsWideColor = mFdp.ConsumeBool(); + config.useContextPriority = mFdp.ConsumeBool(); + config.defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces); + config.defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); + config.wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces); + config.wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); mFlinger->enableLatchUnsignaledConfig = mFdp.PickValueInArray(kLatchUnsignaledConfig); @@ -155,7 +156,7 @@ void SurfaceFlingerFuzzer::invokeFlinger() { } void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() { - ui::DisplayPrimaries primaries; + auto& primaries = mTestableFlinger.mutableConfig().internalDisplayPrimaries; primaries.red.X = mFdp.ConsumeFloatingPoint(); primaries.red.Y = mFdp.ConsumeFloatingPoint(); primaries.red.Z = mFdp.ConsumeFloatingPoint(); @@ -168,7 +169,6 @@ void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() { primaries.white.X = mFdp.ConsumeFloatingPoint(); primaries.white.Y = mFdp.ConsumeFloatingPoint(); primaries.white.Z = mFdp.ConsumeFloatingPoint(); - mTestableFlinger.setInternalDisplayPrimaries(primaries); } void SurfaceFlingerFuzzer::setTransactionState() { diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 0c9a16bee3..97cb5d35e3 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -46,6 +46,7 @@ #include "Scheduler/VsyncModulator.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" +#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerDefaultFactory.h" #include "ThreadContext.h" #include "TimeStats/TimeStats.h" @@ -150,6 +151,8 @@ static constexpr ui::PixelFormat kPixelFormats[] = {ui::PixelFormat::RGBA_8888, ui::PixelFormat::YCBCR_P010, ui::PixelFormat::HSV_888}; +static constexpr int kMaxFrameBufferAcquiredBuffers[] = {2, 3, 4}; + inline VsyncId getFuzzedVsyncId(FuzzedDataProvider& fdp) { return VsyncId{fdp.ConsumeIntegral()}; } @@ -404,6 +407,8 @@ public: SurfaceFlinger *flinger() { return mFlinger.get(); } scheduler::TestableScheduler *scheduler() { return mScheduler; } + auto& mutableConfig() { return mConfig; } + void initializeDisplays() { FTL_FAKE_GUARD(kMainThreadContext, mFlinger->initializeDisplays()); } @@ -695,10 +700,6 @@ public: mFactory.mCreateNativeWindowSurface = f; } - void setInternalDisplayPrimaries(const ui::DisplayPrimaries &primaries) { - memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries)); - } - static auto &mutableLayerDrawingState(const sp &layer) { return layer->mDrawingState; } auto &mutableStateLock() { return mFlinger->mStateLock; } @@ -764,13 +765,12 @@ public: auto calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) const { - return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); + return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } /* Read-write access to private data to set up preconditions and assert * post-conditions. */ - auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplays() { return mFlinger->mDisplays; } auto& mutableDrawingState() { return mFlinger->mDrawingState; } @@ -794,8 +794,8 @@ private: void triggerOnFrameRateOverridesChanged() override {} surfaceflinger::test::Factory mFactory; - sp mFlinger = - sp::make(mFactory, SurfaceFlinger::SkipInitialization); + surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory); + sp mFlinger = sp::make(mConfig); scheduler::TestableScheduler *mScheduler = nullptr; std::shared_ptr mRefreshRateSelector; }; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp index 849a896ce2..c16a005f0d 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp @@ -17,13 +17,15 @@ #include #include "SurfaceFlinger.h" +#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerDefaultFactory.h" using namespace android; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { DefaultFactory factory; - sp flinger = sp::make(factory); + surfaceflinger::Config config = surfaceflinger::Config::makeDefault(&factory); + sp flinger = sp::make(config); flinger->init(); sp composerAIDL = sp::make(flinger); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index e32cf8863b..7124f879e9 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -34,7 +34,7 @@ DisplayTransactionTest::DisplayTransactionTest(bool withMockScheduler) { ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - mFlinger.mutableSupportsWideColor() = false; + mFlinger.mutableConfig().supportsWideColor = false; mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; mFlinger.setCreateBufferQueueFunction([](auto, auto, auto) { diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index ee12276994..5599a7a600 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -684,7 +684,7 @@ struct WideColorNotSupportedVariant { static constexpr bool WIDE_COLOR_SUPPORTED = false; static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableSupportsWideColor() = true; + test->mFlinger.mutableConfig().supportsWideColor = true; } static void setupComposerCallExpectations(DisplayTransactionTest* test) { @@ -699,7 +699,7 @@ struct WideColorSupportNotConfiguredVariant { static constexpr bool WIDE_COLOR_SUPPORTED = false; static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableSupportsWideColor() = false; + test->mFlinger.mutableConfig().supportsWideColor = false; test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index fab3c0e887..6c14f6e1c1 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -250,10 +250,8 @@ TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); - const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers(); - mFlinger.mutableMinAcquiredBuffers() = 2; + mFlinger.mutableConfig().minAcquiredBuffers = 2; EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); - mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers; } MATCHER(Is120Hz, "") { diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp index 5951c9893f..fe383846d1 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp @@ -84,9 +84,7 @@ TEST_F(GetDisplayNativePrimaries, internalDisplayWithPrimariesData) { injector.inject(); auto internalDisplayToken = injector.token(); - ui::DisplayPrimaries expectedPrimaries; - populateDummyDisplayNativePrimaries(expectedPrimaries); - mFlinger.setInternalDisplayPrimaries(expectedPrimaries); + populateDummyDisplayNativePrimaries(mFlinger.mutableConfig().internalDisplayPrimaries); ui::DisplayPrimaries primaries; EXPECT_EQ(NO_ERROR, mFlinger.getDisplayNativePrimaries(internalDisplayToken, primaries)); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp index c0796df6cb..61891c14c7 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp @@ -36,7 +36,7 @@ struct WideColorP3ColorimetricSupportedVariant { static constexpr bool WIDE_COLOR_SUPPORTED = true; static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableSupportsWideColor() = true; + test->mFlinger.mutableConfig().supportsWideColor = true; test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 156c40a721..099abf59b4 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -45,6 +45,8 @@ #include "Scheduler/RefreshRateSelector.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" +#include "SurfaceFlingerConfig.h" +#include "SurfaceFlingerDefaultFactory.h" #include "TestableScheduler.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplayMode.h" @@ -168,13 +170,15 @@ public: TestableSurfaceFlinger(sp flinger = nullptr) : mFlinger(flinger) { if (!mFlinger) { - mFlinger = sp::make(mFactory, SurfaceFlinger::SkipInitialization); + mFlinger = sp::make(mConfig); } } SurfaceFlinger* flinger() { return mFlinger.get(); } scheduler::TestableScheduler* scheduler() { return mScheduler; } + auto& mutableConfig() { return mConfig; } + // Extend this as needed for accessing SurfaceFlinger private (and public) // functions. @@ -312,10 +316,6 @@ public: mFactory.mCreateNativeWindowSurface = f; } - void setInternalDisplayPrimaries(const ui::DisplayPrimaries& primaries) { - memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries)); - } - static auto& mutableLayerDrawingState(const sp& layer) { return layer->mDrawingState; } auto& mutableStateLock() { return mFlinger->mStateLock; } @@ -513,7 +513,7 @@ public: auto calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) const { - return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); + return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } auto setDesiredDisplayModeSpecs(const sp& displayToken, @@ -596,8 +596,6 @@ public: const auto& hwcPhysicalDisplayIdMap() const { return getHwComposer().mPhysicalDisplayIdMap; } const auto& hwcDisplayData() const { return getHwComposer().mDisplayData; } - auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; } - auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } auto& mutableDisplays() { return mFlinger->mDisplays; } @@ -622,8 +620,6 @@ public: return SurfaceFlinger::sActiveDisplayRotationFlags; } - auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; } - auto fromHandle(const sp& handle) { return LayerHandle::getLayer(handle); } ~TestableSurfaceFlinger() { @@ -1008,6 +1004,7 @@ private: static constexpr VsyncId kVsyncId{123}; surfaceflinger::test::Factory mFactory; + surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory); sp mFlinger; scheduler::mock::SchedulerCallback mSchedulerCallback; scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback; -- cgit v1.2.3-59-g8ed1b From 30db640d22bcfaa25d17c7c7bab8fa179d060a75 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Mon, 26 Jun 2023 18:56:51 +0000 Subject: Revert "SF: Introduce struct surfaceflinger::Config" Revert submission 23423266-SF-Config Reason for revert: UIBench Jank Regression reported in b/288665387 Reverted changes: /q/submissionid:23423266-SF-Config Change-Id: I0942f99fec1f211e607e3ff44da2dfa0e30d34c2 --- services/surfaceflinger/Android.bp | 1 - services/surfaceflinger/DisplayDevice.cpp | 24 +- services/surfaceflinger/DisplayDevice.h | 3 +- .../DisplayHardware/FramebufferSurface.cpp | 6 +- .../DisplayHardware/FramebufferSurface.h | 2 +- .../DisplayHardware/VirtualDisplaySurface.cpp | 4 +- .../DisplayHardware/VirtualDisplaySurface.h | 3 +- services/surfaceflinger/Layer.cpp | 6 +- services/surfaceflinger/LayerRenderArea.cpp | 2 +- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 325 ++++++++++++++------- services/surfaceflinger/SurfaceFlinger.h | 113 ++++++- services/surfaceflinger/SurfaceFlingerConfig.cpp | 162 ---------- services/surfaceflinger/SurfaceFlingerConfig.h | 145 --------- services/surfaceflinger/SurfaceFlingerFactory.cpp | 11 +- .../surfaceflinger_displayhardware_fuzzer.cpp | 6 +- .../fuzzer/surfaceflinger_fuzzer.cpp | 30 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 16 +- .../fuzzer/surfaceflinger_service_fuzzer.cpp | 4 +- .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../unittests/DisplayTransactionTestHelpers.h | 4 +- .../tests/unittests/SchedulerTest.cpp | 4 +- ...urfaceFlinger_GetDisplayNativePrimariesTest.cpp | 4 +- ...ceFlinger_SetupNewDisplayDeviceInternalTest.cpp | 2 +- .../tests/unittests/TestableSurfaceFlinger.h | 17 +- 25 files changed, 405 insertions(+), 493 deletions(-) delete mode 100644 services/surfaceflinger/SurfaceFlingerConfig.cpp delete mode 100644 services/surfaceflinger/SurfaceFlingerConfig.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index bf07f7253f..89c80bc83a 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -195,7 +195,6 @@ filegroup { "ScreenCaptureOutput.cpp", "StartPropertySetThread.cpp", "SurfaceFlinger.cpp", - "SurfaceFlingerConfig.cpp", "SurfaceFlingerDefaultFactory.cpp", "Tracing/LayerTracing.cpp", "Tracing/TransactionTracing.cpp", diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 2789fa6bf2..f6ca9e2856 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -78,19 +78,18 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) .setDisplayHeight(ANativeWindow_getHeight(args.nativeWindow.get())) .setNativeWindow(std::move(args.nativeWindow)) .setDisplaySurface(std::move(args.displaySurface)) - .setMaxTextureCacheSize(static_cast( - mFlinger->getConfig().maxFrameBufferAcquiredBuffers)) + .setMaxTextureCacheSize( + static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)) .build()); - if (!mFlinger->getConfig().disableClientCompositionCache && - mFlinger->getConfig().maxFrameBufferAcquiredBuffers > 0) { + if (!mFlinger->mDisableClientCompositionCache && + SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { mCompositionDisplay->createClientCompositionCache( - static_cast(mFlinger->getConfig().maxFrameBufferAcquiredBuffers)); + static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)); } - mCompositionDisplay->setPredictCompositionStrategy( - mFlinger->getConfig().predictCompositionStrategy); - mCompositionDisplay->setTreat170mAsSrgb(mFlinger->getConfig().treat170mAsSrgb); + mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy); + mCompositionDisplay->setTreat170mAsSrgb(mFlinger->mTreat170mAsSrgb); mCompositionDisplay->createDisplayColorProfile( compositionengine::DisplayColorProfileCreationArgsBuilder() .setHasWideColorGamut(args.hasWideColorGamut) @@ -412,22 +411,23 @@ HdrCapabilities DisplayDevice::getHdrCapabilities() const { capabilities.getDesiredMinLuminance()); } -void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc) { +void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, + bool showRenderRate, bool showInMiddle) { if (!enable) { mRefreshRateOverlay.reset(); return; } ftl::Flags features; - if (mFlinger->getConfig().refreshRateOverlay.showSpinner) { + if (showSpinner) { features |= RefreshRateOverlay::Features::Spinner; } - if (mFlinger->getConfig().refreshRateOverlay.showRenderRate) { + if (showRenderRate) { features |= RefreshRateOverlay::Features::RenderRate; } - if (mFlinger->getConfig().refreshRateOverlay.showInMiddle) { + if (showInMiddle) { features |= RefreshRateOverlay::Features::ShowInMiddle; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d2a9fb685a..dc5f8a85af 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -236,7 +236,8 @@ public: } // Enables an overlay to be displayed with the current refresh rate - void enableRefreshRateOverlay(bool enable, bool setByHwc) REQUIRES(kMainThreadContext); + void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate, + bool showInMiddle) REQUIRES(kMainThreadContext); void updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc = false); bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; } bool onKernelTimerChanged(std::optional, bool timerExpired); diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 14fff772db..ce602a8ad9 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -50,8 +50,7 @@ using ui::Dataspace; FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId, const sp& consumer, - const ui::Size& size, const ui::Size& maxSize, - int maxAcquiredBufferCount) + const ui::Size& size, const ui::Size& maxSize) : ConsumerBase(consumer), mDisplayId(displayId), mMaxSize(maxSize), @@ -71,7 +70,8 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displa GRALLOC_USAGE_HW_COMPOSER); const auto limitedSize = limitSize(size); mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height); - mConsumer->setMaxAcquiredBufferCount(maxAcquiredBufferCount); + mConsumer->setMaxAcquiredBufferCount( + SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1); for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) { mHwcBufferIds[i] = UINT64_MAX; diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 5a1d14fdfe..0b863daf47 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -42,7 +42,7 @@ class FramebufferSurface : public ConsumerBase, public compositionengine::Displa public: FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId, const sp& consumer, const ui::Size& size, - const ui::Size& maxSize, int maxAcquiredBufferCount); + const ui::Size& maxSize); virtual status_t beginFrame(bool mustRecompose); virtual status_t prepareFrame(CompositionType compositionType); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index d759c12612..d62075ec65 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -50,7 +50,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId d const sp& sink, const sp& bqProducer, const sp& bqConsumer, - const std::string& name, bool useHwcForRgbToYuv) + const std::string& name) : ConsumerBase(bqConsumer), mHwc(hwc), mDisplayId(displayId), @@ -69,7 +69,7 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId d mOutputFence(Fence::NO_FENCE), mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT), - mForceHwcCopy(useHwcForRgbToYuv) { + mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) { mSource[SOURCE_SINK] = sink; mSource[SOURCE_SCRATCH] = bqProducer; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 8a56d5f7b5..be06e2bb10 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -77,8 +77,7 @@ class VirtualDisplaySurface : public compositionengine::DisplaySurface, public: VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp& sink, const sp& bqProducer, - const sp& bqConsumer, const std::string& name, - bool useHwcForRgbToYuv); + const sp& bqConsumer, const std::string& name); // // DisplaySurface interface diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8e1b8f2c00..5a010e8af6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2562,7 +2562,7 @@ bool Layer::hasInputInfo() const { compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( const DisplayDevice* display) const { if (!display) return nullptr; - if (!mFlinger->getConfig().layerLifecycleManagerEnabled) { + if (!mFlinger->mLayerLifecycleManagerEnabled) { return display->getCompositionDisplay()->getOutputLayerForLayer( getCompositionEngineLayerFE()); } @@ -2907,7 +2907,7 @@ void Layer::onSurfaceFrameCreated( void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { - if (mFlinger->getConfig().layerLifecycleManagerEnabled) { + if (mFlinger->mLayerLifecycleManagerEnabled) { handle->transformHint = mTransformHint; } else { handle->transformHint = mSkipReportingTransformHint @@ -3162,7 +3162,7 @@ bool Layer::setBuffer(std::shared_ptr& buffer, mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(), mOwnerUid, postTime, getGameMode()); - if (mFlinger->getConfig().legacyFrontEndEnabled) { + if (mFlinger->mLegacyFrontEndEnabled) { recordLayerHistoryBufferUpdate(getLayerProps()); } diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp index 9c1944b122..51d4ff854f 100644 --- a/services/surfaceflinger/LayerRenderArea.cpp +++ b/services/surfaceflinger/LayerRenderArea.cpp @@ -78,7 +78,7 @@ void LayerRenderArea::render(std::function drawLayers) { mTransform = mLayerTransform.inverse(); } - if (mFlinger.getConfig().layerLifecycleManagerEnabled) { + if (mFlinger.mLayerLifecycleManagerEnabled) { drawLayers(); return; } diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 03f3b402c9..8f658d5a09 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -322,7 +322,7 @@ void RegionSamplingThread::captureSample() { }; std::function>>()> getLayerSnapshots; - if (mFlinger.getConfig().layerLifecycleManagerEnabled) { + if (mFlinger.mLayerLifecycleManagerEnabled) { auto filterFn = [&](const frontend::LayerSnapshot& snapshot, bool& outStopTraversal) -> bool { const Rect bounds = diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 60c09049cf..ba13293a8f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -214,6 +214,16 @@ static constexpr int FOUR_K_HEIGHT = 2160; // TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity. constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; +float getDensityFromProperty(const char* property, bool required) { + char value[PROPERTY_VALUE_MAX]; + const float density = property_get(property, value, nullptr) > 0 ? std::atof(value) : 0.f; + if (!density && required) { + ALOGE("%s must be defined as a build property", property); + return FALLBACK_DENSITY; + } + return density; +} + // Currently we only support V0_SRGB and DISPLAY_P3 as composition preference. bool validateCompositionDataspace(Dataspace dataspace) { return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3; @@ -312,6 +322,18 @@ const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB // --------------------------------------------------------------------------- +int64_t SurfaceFlinger::dispSyncPresentTimeOffset; +bool SurfaceFlinger::useHwcForRgbToYuv; +bool SurfaceFlinger::hasSyncFramework; +int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; +int64_t SurfaceFlinger::minAcquiredBuffers = 1; +uint32_t SurfaceFlinger::maxGraphicsWidth; +uint32_t SurfaceFlinger::maxGraphicsHeight; +bool SurfaceFlinger::useContextPriority; +Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB; +ui::PixelFormat SurfaceFlinger::defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888; +Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB; +ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; LatchUnsignaledConfig SurfaceFlinger::enableLatchUnsignaledConfig; std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { @@ -338,35 +360,136 @@ bool callingThreadHasPermission(const String16& permission) { ui::Transform::RotationFlags SurfaceFlinger::sActiveDisplayRotationFlags = ui::Transform::ROT_0; -SurfaceFlinger::SurfaceFlinger(surfaceflinger::Config& config) - : mConfig(&config), - mDebugFlashDelay(base::GetUintProperty("debug.sf.showupdates"s, 0u)), +SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) + : mFactory(factory), + mPid(getpid()), mTimeStats(std::make_shared()), - mFrameTracer(mConfig->factory->createFrameTracer()), - mFrameTimeline(mConfig->factory->createFrameTimeline(mTimeStats, mConfig->pid)), - mCompositionEngine(mConfig->factory->createCompositionEngine()), + mFrameTracer(mFactory.createFrameTracer()), + mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)), + mCompositionEngine(mFactory.createCompositionEngine()), + mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)), mTunnelModeEnabledReporter(sp::make()), + mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)), + mInternalDisplayDensity( + getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)), mPowerAdvisor(std::make_unique(*this)), mWindowInfosListenerInvoker(sp::make()) { + ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str()); +} + +SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { ATRACE_CALL(); - ALOGI("SurfaceFlinger is starting."); - ALOGI("Using HWComposer service: %s", mConfig->hwcServiceName.c_str()); - ALOGI_IF(mConfig->backpressureGpuComposition, "Enabling backpressure for GPU composition"); - ALOGI_IF(!mConfig->supportsBlur, "Disabling blur effects, they are not supported."); - ALOGI_IF(mConfig->trebleTestingOverride, "Enabling Treble testing override"); + ALOGI("SurfaceFlinger is starting"); + + hasSyncFramework = running_without_sync_framework(true); + + dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0); + + useHwcForRgbToYuv = force_hwc_copy_for_virtual_displays(false); + + maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); + minAcquiredBuffers = + SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers); + + maxGraphicsWidth = std::max(max_graphics_width(0), 0); + maxGraphicsHeight = std::max(max_graphics_height(0), 0); + + mSupportsWideColor = has_wide_color_display(false); + mDefaultCompositionDataspace = + static_cast(default_composition_dataspace(Dataspace::V0_SRGB)); + mWideColorGamutCompositionDataspace = static_cast(wcg_composition_dataspace( + mSupportsWideColor ? Dataspace::DISPLAY_P3 : Dataspace::V0_SRGB)); + defaultCompositionDataspace = mDefaultCompositionDataspace; + wideColorGamutCompositionDataspace = mWideColorGamutCompositionDataspace; + defaultCompositionPixelFormat = static_cast( + default_composition_pixel_format(ui::PixelFormat::RGBA_8888)); + wideColorGamutCompositionPixelFormat = + static_cast(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888)); + + mColorSpaceAgnosticDataspace = + static_cast(color_space_agnostic_dataspace(Dataspace::UNKNOWN)); + + mLayerCachingEnabled = [] { + const bool enable = + android::sysprop::SurfaceFlingerProperties::enable_layer_caching().value_or(false); + return base::GetBoolProperty(std::string("debug.sf.enable_layer_caching"), enable); + }(); + + useContextPriority = use_context_priority(true); + + mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries(); - if (mConfig->trebleTestingOverride) { + // debugging stuff... + char value[PROPERTY_VALUE_MAX]; + + property_get("ro.build.type", value, "user"); + mIsUserBuild = strcmp(value, "user") == 0; + + mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u); + + mBackpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, true); + ALOGI_IF(mBackpressureGpuComposition, "Enabling backpressure for GPU composition"); + + property_get("ro.surface_flinger.supports_background_blur", value, "0"); + bool supportsBlurs = atoi(value); + mSupportsBlur = supportsBlurs; + ALOGI_IF(!mSupportsBlur, "Disabling blur effects, they are not supported."); + + const size_t defaultListSize = MAX_LAYERS; + auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); + mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; + mGraphicBufferProducerListSizeLogThreshold = + std::max(static_cast(0.95 * + static_cast(mMaxGraphicBufferProducerListSize)), + 1); + + property_get("debug.sf.luma_sampling", value, "1"); + mLumaSampling = atoi(value); + + property_get("debug.sf.disable_client_composition_cache", value, "0"); + mDisableClientCompositionCache = atoi(value); + + property_get("debug.sf.predict_hwc_composition_strategy", value, "1"); + mPredictCompositionStrategy = atoi(value); + + property_get("debug.sf.treat_170m_as_sRGB", value, "0"); + mTreat170mAsSrgb = atoi(value); + + mIgnoreHwcPhysicalDisplayOrientation = + base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, false); + + // We should be reading 'persist.sys.sf.color_saturation' here + // but since /data may be encrypted, we need to wait until after vold + // comes online to attempt to read the property. The property is + // instead read after the boot animation + + if (base::GetBoolProperty("debug.sf.treble_testing_override"s, false)) { // Without the override SurfaceFlinger cannot connect to HIDL // services that are not listed in the manifests. Considered // deriving the setting from the set service name, but it // would be brittle if the name that's not 'default' is used // for production purposes later on. + ALOGI("Enabling Treble testing override"); android::hardware::details::setTrebleTestingOverride(true); } - if (!mConfig->isUserBuild && mConfig->enableTransactionTracing) { + // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner + mRefreshRateOverlaySpinner = property_get_bool("debug.sf.show_refresh_rate_overlay_spinner", 0); + mRefreshRateOverlayRenderRate = + property_get_bool("debug.sf.show_refresh_rate_overlay_render_rate", 0); + mRefreshRateOverlayShowInMiddle = + property_get_bool("debug.sf.show_refresh_rate_overlay_in_middle", 0); + + if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) { mTransactionTracing.emplace(); } + + mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false); + + mLayerLifecycleManagerEnabled = + base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, false); + mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled || + base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false); } LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() { @@ -693,18 +816,17 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { // Get a RenderEngine for the given display / config (can't fail) // TODO(b/77156734): We need to stop casting and use HAL types when possible. // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display. - auto builder = - renderengine::RenderEngineCreationArgs::Builder() - .setPixelFormat(static_cast(mConfig->defaultCompositionPixelFormat)) - .setImageCacheSize(mConfig->maxFrameBufferAcquiredBuffers) - .setUseColorManagerment(useColorManagement) - .setEnableProtectedContext(enable_protected_contents(false)) - .setPrecacheToneMapperShaderOnly(false) - .setSupportsBackgroundBlur(mConfig->supportsBlur) - .setContextPriority( - mConfig->useContextPriority - ? renderengine::RenderEngine::ContextPriority::REALTIME - : renderengine::RenderEngine::ContextPriority::MEDIUM); + auto builder = renderengine::RenderEngineCreationArgs::Builder() + .setPixelFormat(static_cast(defaultCompositionPixelFormat)) + .setImageCacheSize(maxFrameBufferAcquiredBuffers) + .setUseColorManagerment(useColorManagement) + .setEnableProtectedContext(enable_protected_contents(false)) + .setPrecacheToneMapperShaderOnly(false) + .setSupportsBackgroundBlur(mSupportsBlur) + .setContextPriority( + useContextPriority + ? renderengine::RenderEngine::ContextPriority::REALTIME + : renderengine::RenderEngine::ContextPriority::MEDIUM); if (auto type = chooseRenderEngineTypeViaSysProp()) { builder.setRenderEngineType(type.value()); } @@ -719,7 +841,7 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { } mCompositionEngine->setTimeStats(mTimeStats); - mCompositionEngine->setHwComposer(getFactory().createHWComposer(mConfig->hwcServiceName)); + mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName)); mCompositionEngine->getHwComposer().setCallback(*this); ClientCache::getInstance().setRenderEngine(&getRenderEngine()); @@ -909,11 +1031,11 @@ status_t SurfaceFlinger::getStaticDisplayInfo(int64_t displayId, ui::StaticDispl info->connectionType = snapshot.connectionType(); info->deviceProductInfo = snapshot.deviceProductInfo(); - if (mConfig->emulatedDisplayDensity) { - info->density = mConfig->emulatedDisplayDensity; + if (mEmulatedDisplayDensity) { + info->density = mEmulatedDisplayDensity; } else { info->density = info->connectionType == ui::DisplayConnectionType::Internal - ? mConfig->internalDisplayDensity + ? mInternalDisplayDensity : FALLBACK_DENSITY; } info->density /= ACONFIGURATION_DENSITY_MEDIUM; @@ -976,7 +1098,7 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info info->supportedDisplayModes.push_back(outMode); } - info->supportedColorModes = snapshot.filterColorModes(mConfig->supportsWideColor); + info->supportedColorModes = snapshot.filterColorModes(mSupportsWideColor); const PhysicalDisplayId displayId = snapshot.displayId(); @@ -1374,7 +1496,7 @@ status_t SurfaceFlinger::getDisplayNativePrimaries(const sp& displayTok } // TODO(b/229846990): For now, assume that all internal displays have the same primaries. - primaries = mConfig->internalDisplayPrimaries; + primaries = mInternalDisplayPrimaries; return NO_ERROR; } @@ -1398,7 +1520,7 @@ status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, ui: const auto& [display, snapshotRef] = *displayOpt; const auto& snapshot = snapshotRef.get(); - const auto modes = snapshot.filterColorModes(mConfig->supportsWideColor); + const auto modes = snapshot.filterColorModes(mSupportsWideColor); const bool exists = std::find(modes.begin(), modes.end(), mode) != modes.end(); if (mode < ui::ColorMode::NATIVE || !exists) { @@ -1704,7 +1826,7 @@ status_t SurfaceFlinger::isWideColorDisplay(const sp& displayToken, } *outIsWideColorDisplay = - display->isPrimary() ? mConfig->supportsWideColor : display->hasWideColorGamut(); + display->isPrimary() ? mSupportsWideColor : display->hasWideColorGamut(); return NO_ERROR; } @@ -1725,12 +1847,10 @@ status_t SurfaceFlinger::getCompositionPreference( Dataspace* outDataspace, ui::PixelFormat* outPixelFormat, Dataspace* outWideColorGamutDataspace, ui::PixelFormat* outWideColorGamutPixelFormat) const { - *outDataspace = - mOverrideDefaultCompositionDataspace.value_or(mConfig->defaultCompositionDataspace); - *outPixelFormat = mConfig->defaultCompositionPixelFormat; - *outWideColorGamutDataspace = mOverrideWideColorGamutCompositionDataspace.value_or( - mConfig->wideColorGamutCompositionDataspace); - *outWideColorGamutPixelFormat = mConfig->wideColorGamutCompositionPixelFormat; + *outDataspace = mDefaultCompositionDataspace; + *outPixelFormat = defaultCompositionPixelFormat; + *outWideColorGamutDataspace = mWideColorGamutCompositionDataspace; + *outWideColorGamutPixelFormat = wideColorGamutCompositionPixelFormat; return NO_ERROR; } @@ -2193,7 +2313,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, .displays = mFrontEndDisplayInfos, .displayChanges = mFrontEndDisplayInfosChanged, .globalShadowSettings = mDrawingState.globalShadowSettings, - .supportsBlur = mConfig->supportsBlur, + .supportsBlur = mSupportsBlur, .forceFullDamage = mForceFullDamage, .supportedLayerGenericMetadata = getHwComposer().getSupportedLayerGenericMetadata(), @@ -2213,7 +2333,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0; bool newDataLatched = false; - if (!mConfig->legacyFrontEndEnabled) { + if (!mLegacyFrontEndEnabled) { ATRACE_NAME("DisplayCallbackAndStatsUpdates"); applyTransactions(update.transactions, vsyncId); const nsecs_t latchTime = systemTime(); @@ -2307,7 +2427,7 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) } if (pacesetterFrameTarget.isFramePending()) { - if (mConfig->backpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) { + if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) { scheduleCommit(FrameHint::kNone); return false; } @@ -2338,7 +2458,7 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod); } - if (mConfig->refreshRateOverlay.showSpinner) { + if (mRefreshRateOverlaySpinner) { Mutex::Autolock lock(mStateLock); if (const auto display = getDefaultDisplayDeviceLocked()) { display->animateRefreshRateOverlay(); @@ -2354,12 +2474,12 @@ bool SurfaceFlinger::commit(const scheduler::FrameTarget& pacesetterFrameTarget) const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded); bool transactionsAreEmpty; - if (mConfig->legacyFrontEndEnabled) { + if (mLegacyFrontEndEnabled) { mustComposite |= updateLayerSnapshotsLegacy(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(), flushTransactions, transactionsAreEmpty); } - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { mustComposite |= updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(), flushTransactions, transactionsAreEmpty); @@ -2465,7 +2585,7 @@ CompositeResult SurfaceFlinger::composite(scheduler::FrameTargeter& pacesetterFr refreshArgs.outputColorSetting = useColorManagement ? mDisplayColorSetting : compositionengine::OutputColorSetting::kUnmanaged; - refreshArgs.colorSpaceAgnosticDataspace = mConfig->colorSpaceAgnosticDataspace; + refreshArgs.colorSpaceAgnosticDataspace = mColorSpaceAgnosticDataspace; refreshArgs.forceOutputColorMode = mForceColorMode; refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty; @@ -2619,7 +2739,7 @@ bool SurfaceFlinger::isHdrLayer(const frontend::LayerSnapshot& snapshot) const { // Even though the camera layer may be using an HDR transfer function or otherwise be "HDR" // the device may need to avoid boosting the brightness as a result of these layers to // reduce power consumption during camera recording - if (mConfig->ignoreHdrCameraLayers) { + if (mIgnoreHdrCameraLayers) { if (snapshot.externalTexture && (snapshot.externalTexture->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) { return false; @@ -2650,7 +2770,7 @@ ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId, if (!id) { return ui::ROTATION_0; } - if (!mConfig->ignoreHwcPhysicalDisplayOrientation && + if (!mIgnoreHwcPhysicalDisplayOrientation && getHwComposer().getComposer()->isSupported( Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) { switch (getHwComposer().getPhysicalDisplayOrientation(*id)) { @@ -2817,7 +2937,7 @@ void SurfaceFlinger::postComposition(scheduler::FrameTargeter& pacesetterFrameTa } }; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { mLayerSnapshotBuilder.forEachVisibleSnapshot( [&, compositionDisplay = compositionDisplay]( std::unique_ptr& snapshot) { @@ -2869,7 +2989,7 @@ void SurfaceFlinger::postComposition(scheduler::FrameTargeter& pacesetterFrameTa const bool isDisplayConnected = defaultDisplay && getHwComposer().isConnected(defaultDisplay->getPhysicalId()); - if (!mConfig->hasSyncFramework) { + if (!hasSyncFramework) { if (isDisplayConnected && defaultDisplay->isPoweredOn()) { mScheduler->enableHardwareVsync(defaultDisplay->getPhysicalId()); } @@ -2910,7 +3030,7 @@ void SurfaceFlinger::postComposition(scheduler::FrameTargeter& pacesetterFrameTa if (!layer->hasTrustedPresentationListener()) { return; } - const frontend::LayerSnapshot* snapshot = mConfig->layerLifecycleManagerEnabled + const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled ? mLayerSnapshotBuilder.getSnapshot(layer->sequence) : layer->getLayerSnapshot(); std::optional displayOpt = std::nullopt; @@ -3305,7 +3425,7 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, builder.setPowerAdvisor(mPowerAdvisor.get()); builder.setName(state.displayName); auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); - compositionDisplay->setLayerCachingEnabled(mConfig->layerCachingEnabled); + compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled); sp displaySurface; sp producer; @@ -3317,8 +3437,7 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId()); LOG_FATAL_IF(!displayId); auto surface = sp::make(getHwComposer(), *displayId, state.surface, - bqProducer, bqConsumer, state.displayName, - mConfig->useHwcForRgbToYuv); + bqProducer, bqConsumer, state.displayName); displaySurface = surface; producer = std::move(surface); } else { @@ -3328,11 +3447,10 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, state.surface.get()); const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId()); LOG_FATAL_IF(!displayId); - displaySurface = sp::make(getHwComposer(), *displayId, bqConsumer, - state.physical->activeMode->getResolution(), - ui::Size(mConfig->maxGraphicsWidth, - mConfig->maxGraphicsHeight), - mConfig->maxFrameBufferAcquiredBuffers); + displaySurface = + sp::make(getHwComposer(), *displayId, bqConsumer, + state.physical->activeMode->getResolution(), + ui::Size(maxGraphicsWidth, maxGraphicsHeight)); producer = bqProducer; } @@ -3513,7 +3631,7 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { // Commit display transactions. const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded; mFrontEndDisplayInfosChanged = displayTransactionNeeded; - if (displayTransactionNeeded && !mConfig->layerLifecycleManagerEnabled) { + if (displayTransactionNeeded && !mLayerLifecycleManagerEnabled) { processDisplayChangesLocked(); mFrontEndDisplayInfos.clear(); for (const auto& [_, display] : mDisplays) { @@ -3713,7 +3831,7 @@ void SurfaceFlinger::buildWindowInfos(std::vector& outWindowInfos, outWindowInfos.reserve(sNumWindowInfos); sNumWindowInfos = 0; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { mLayerSnapshotBuilder.forEachInputSnapshot( [&outWindowInfos](const frontend::LayerSnapshot& snapshot) { outWindowInfos.push_back(snapshot.inputInfo); @@ -3837,7 +3955,7 @@ void SurfaceFlinger::initScheduler(const sp& display) { if (display->refreshRateSelector().kernelIdleTimerController()) { features |= Feature::kKernelIdleTimer; } - if (mConfig->backpressureGpuComposition) { + if (mBackpressureGpuComposition) { features |= Feature::kBackpressureGpuComposition; } @@ -4383,7 +4501,7 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC void SurfaceFlinger::addTransactionReadyFilters() { mTransactionHandler.addTransactionReadyFilter( std::bind(&SurfaceFlinger::transactionReadyTimelineCheck, this, std::placeholders::_1)); - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { mTransactionHandler.addTransactionReadyFilter( std::bind(&SurfaceFlinger::transactionReadyBufferCheck, this, std::placeholders::_1)); @@ -4614,7 +4732,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin const std::vector& listenerCallbacks, int originPid, int originUid, uint64_t transactionId) { uint32_t transactionFlags = 0; - if (!mConfig->layerLifecycleManagerEnabled) { + if (!mLayerLifecycleManagerEnabled) { for (DisplayState& display : displays) { transactionFlags |= setDisplayStateLocked(display); } @@ -4629,12 +4747,12 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin uint32_t clientStateFlags = 0; for (auto& resolvedState : states) { - if (mConfig->legacyFrontEndEnabled) { + if (mLegacyFrontEndEnabled) { clientStateFlags |= setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime, isAutoTimestamp, postTime, transactionId); - } else /* mConfig->layerLifecycleManagerEnabled */ { + } else /*mLayerLifecycleManagerEnabled*/ { clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, desiredPresentTime, isAutoTimestamp, postTime, transactionId); @@ -4708,7 +4826,7 @@ bool SurfaceFlinger::applyAndCommitDisplayTransactionStates( } mFrontEndDisplayInfosChanged = mTransactionFlags & eDisplayTransactionNeeded; - if (mFrontEndDisplayInfosChanged && !mConfig->legacyFrontEndEnabled) { + if (mFrontEndDisplayInfosChanged && !mLegacyFrontEndEnabled) { processDisplayChangesLocked(); mFrontEndDisplayInfos.clear(); for (const auto& [_, display] : mDisplays) { @@ -4911,7 +5029,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime if (layer->setCornerRadius(s.cornerRadius)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eBackgroundBlurRadiusChanged && mConfig->supportsBlur) { + if (what & layer_state_t::eBackgroundBlurRadiusChanged && mSupportsBlur) { if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded; } if (what & layer_state_t::eBlurRegionsChanged) { @@ -5315,7 +5433,7 @@ status_t SurfaceFlinger::mirrorDisplay(DisplayId displayId, const LayerCreationA return result; } - if (mConfig->legacyFrontEndEnabled) { + if (mLegacyFrontEndEnabled) { std::scoped_lock lock(mMirrorDisplayLock); mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client); } @@ -5422,10 +5540,9 @@ void SurfaceFlinger::initializeDisplays() { const nsecs_t now = systemTime(); state.desiredPresentTime = now; state.postTime = now; - state.originPid = mConfig->pid; + state.originPid = mPid; state.originUid = static_cast(getuid()); - const uint64_t transactionId = - (static_cast(mConfig->pid) << 32) | mUniqueTransactionId++; + const uint64_t transactionId = (static_cast(mPid) << 32) | mUniqueTransactionId++; state.id = transactionId; // reset screen orientation and use primary layer stack @@ -5445,7 +5562,7 @@ void SurfaceFlinger::initializeDisplays() { std::vector transactions; transactions.emplace_back(state); - if (mConfig->legacyFrontEndEnabled) { + if (mLegacyFrontEndEnabled) { applyTransactions(transactions, VsyncId{0}); } else { applyAndCommitDisplayTransactionStates(transactions); @@ -5741,13 +5858,13 @@ void SurfaceFlinger::logFrameStats(TimePoint now) { void SurfaceFlinger::appendSfConfigString(std::string& result) const { result.append(" [sf"); - StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, mConfig->dispSyncPresentTimeOffset); - StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", mConfig->useHwcForRgbToYuv); + StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset); + StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv); StringAppendF(&result, " MAX_VIRT_DISPLAY_DIM=%zu", getHwComposer().getMaxVirtualDisplayDimension()); - StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !mConfig->hasSyncFramework); + StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework); StringAppendF(&result, " NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64, - mConfig->maxFrameBufferAcquiredBuffers); + maxFrameBufferAcquiredBuffers); result.append("]"); } @@ -5767,7 +5884,7 @@ void SurfaceFlinger::dumpScheduler(std::string& result) const { StringAppendF(&result, " present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n", - mConfig->dispSyncPresentTimeOffset, getVsyncPeriodFromHWC()); + dispSyncPresentTimeOffset, getVsyncPeriodFromHWC()); } void SurfaceFlinger::dumpEvents(std::string& result) const { @@ -5866,7 +5983,7 @@ void SurfaceFlinger::dumpRawDisplayIdentificationData(const DumpArgs& args, } void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { - StringAppendF(&result, "Device supports wide color: %d\n", mConfig->supportsWideColor); + StringAppendF(&result, "Device supports wide color: %d\n", mSupportsWideColor); StringAppendF(&result, "Device uses color management: %d\n", useColorManagement); StringAppendF(&result, "DisplayColorSetting: %s\n", decodeDisplayColorSetting(mDisplayColorSetting).c_str()); @@ -5900,7 +6017,7 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } } - if (mConfig->legacyFrontEndEnabled) { + if (mLegacyFrontEndEnabled) { LayersProto layersProto; for (const sp& layer : mDrawingState.layersSortedByZ) { if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { @@ -6557,7 +6674,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r if (!validateCompositionDataspace(dataspace)) { return BAD_VALUE; } - mOverrideDefaultCompositionDataspace = dataspace; + mDefaultCompositionDataspace = dataspace; } n = data.readInt32(); if (n) { @@ -6565,12 +6682,12 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r if (!validateCompositionDataspace(dataspace)) { return BAD_VALUE; } - mOverrideWideColorGamutCompositionDataspace = dataspace; + mWideColorGamutCompositionDataspace = dataspace; } } else { - // Reset data space overrides. - mOverrideDefaultCompositionDataspace.reset(); - mOverrideWideColorGamutCompositionDataspace.reset(); + // restore composition data space. + mDefaultCompositionDataspace = defaultCompositionDataspace; + mWideColorGamutCompositionDataspace = wideColorGamutCompositionDataspace; } return NO_ERROR; } @@ -6709,10 +6826,10 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } { Mutex::Autolock lock(mStateLock); - mConfig->layerCachingEnabled = n != 0; + mLayerCachingEnabled = n != 0; for (const auto& [_, display] : mDisplays) { if (!inputId || *inputId == display->getPhysicalId()) { - display->enableLayerCaching(mConfig->layerCachingEnabled); + display->enableLayerCaching(mLayerCachingEnabled); } } } @@ -7037,7 +7154,7 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, }); GetLayerSnapshotsFunction getLayerSnapshots; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); } else { @@ -7080,7 +7197,7 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, }); GetLayerSnapshotsFunction getLayerSnapshots; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, /*snapshotFilterFn=*/nullptr); } else { @@ -7176,7 +7293,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr { ui::Transform layerTransform; Rect layerBufferSize; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { frontend::LayerSnapshot* snapshot = mLayerSnapshotBuilder.getSnapshot(parent->getSequence()); if (!snapshot) { @@ -7196,7 +7313,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, args.hintForSeamlessTransition); }); GetLayerSnapshotsFunction getLayerSnapshots; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { std::optional parentCrop = std::nullopt; if (args.childrenOnly) { parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height) @@ -7449,7 +7566,7 @@ ftl::SharedFuture SurfaceFlinger::renderScreenImpl( layerStack, regionSampling, renderArea = std::move(renderArea), renderIntent]() -> FenceResult { std::unique_ptr compositionEngine = - mConfig->factory->createCompositionEngine(); + mFactory.createCompositionEngine(); compositionEngine->setRenderEngine(mRenderEngine.get()); compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace, @@ -7519,7 +7636,7 @@ ftl::SharedFuture SurfaceFlinger::renderScreenImpl( } void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const { - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { for (auto& layer : mLegacyLayers) { visitor(layer.second.get()); } @@ -7841,7 +7958,9 @@ void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { } if (const auto device = getDisplayDeviceLocked(id)) { - device->enableRefreshRateOverlay(enable, setByHwc); + device->enableRefreshRateOverlay(enable, setByHwc, mRefreshRateOverlaySpinner, + mRefreshRateOverlayRenderRate, + mRefreshRateOverlayShowInMiddle); } } } @@ -7852,12 +7971,12 @@ int SurfaceFlinger::getGpuContextPriority() { } int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate, - std::chrono::nanoseconds presentLatency) const { + std::chrono::nanoseconds presentLatency) { auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); if (presentLatency.count() % refreshRate.getPeriodNsecs()) { pipelineDepth++; } - return std::max(mConfig->minAcquiredBuffers, static_cast(pipelineDepth - 1)); + return std::max(minAcquiredBuffers, static_cast(pipelineDepth - 1)); } status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const { @@ -7939,7 +8058,7 @@ void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state, Vs } void SurfaceFlinger::sample() { - if (!mConfig->lumaSampling || !mRegionSamplingThread) { + if (!mLumaSampling || !mRegionSamplingThread) { return; } @@ -8131,7 +8250,7 @@ void SurfaceFlinger::updateLayerMetadataSnapshot() { void SurfaceFlinger::moveSnapshotsFromCompositionArgs( compositionengine::CompositionRefreshArgs& refreshArgs, const std::vector>& layers) { - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { std::vector>& snapshots = mLayerSnapshotBuilder.getSnapshots(); for (auto [_, layerFE] : layers) { @@ -8139,7 +8258,7 @@ void SurfaceFlinger::moveSnapshotsFromCompositionArgs( snapshots[i] = std::move(layerFE->mSnapshot); } } - if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) { + if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) { for (auto [layer, layerFE] : layers) { layer->updateLayerSnapshot(std::move(layerFE->mSnapshot)); } @@ -8149,7 +8268,7 @@ void SurfaceFlinger::moveSnapshotsFromCompositionArgs( std::vector> SurfaceFlinger::moveSnapshotsToCompositionArgs( compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly) { std::vector> layers; - if (mConfig->layerLifecycleManagerEnabled) { + if (mLayerLifecycleManagerEnabled) { nsecs_t currentTime = systemTime(); mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr& snapshot) { @@ -8175,7 +8294,7 @@ std::vector> SurfaceFlinger::moveSnapshotsToComposit layers.emplace_back(legacyLayer.get(), layerFE.get()); }); } - if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) { + if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) { auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) { if (const auto& layerFE = layer->getCompositionEngineLayerFE()) { if (cursorOnly && @@ -8267,7 +8386,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(std::optional la .displays = mFrontEndDisplayInfos, .displayChanges = true, .globalShadowSettings = mDrawingState.globalShadowSettings, - .supportsBlur = mConfig->supportsBlur, + .supportsBlur = mSupportsBlur, .forceFullDamage = mForceFullDamage, .excludeLayerIds = std::move(excludeLayerIds), .supportedLayerGenericMetadata = @@ -8301,7 +8420,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t u .displays = mFrontEndDisplayInfos, .displayChanges = true, .globalShadowSettings = mDrawingState.globalShadowSettings, - .supportsBlur = mConfig->supportsBlur, + .supportsBlur = mSupportsBlur, .forceFullDamage = mForceFullDamage, .parentCrop = parentCrop, .excludeLayerIds = std::move(excludeLayerIds), diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 55e1b758b7..5c57abdb32 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -63,7 +63,6 @@ #include #include -#include "Client.h" #include "Display/PhysicalDisplay.h" #include "DisplayDevice.h" #include "DisplayHardware/HWC2.h" @@ -82,7 +81,6 @@ #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/RefreshRateStats.h" #include "Scheduler/Scheduler.h" -#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerFactory.h" #include "ThreadContext.h" #include "Tracing/LayerTracing.h" @@ -109,6 +107,7 @@ #include #include +#include "Client.h" using namespace android::surfaceflinger; @@ -198,7 +197,10 @@ class SurfaceFlinger : public BnSurfaceComposer, private scheduler::ISchedulerCallback, private compositionengine::ICEPowerCallback { public: - explicit SurfaceFlinger(surfaceflinger::Config&) ANDROID_API; + struct SkipInitializationTag {}; + + SurfaceFlinger(surfaceflinger::Factory&, SkipInitializationTag) ANDROID_API; + explicit SurfaceFlinger(surfaceflinger::Factory&) ANDROID_API; // set main thread scheduling policy static status_t setSchedFifo(bool enabled) ANDROID_API; @@ -208,9 +210,51 @@ public: static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; } + // If fences from sync Framework are supported. + static bool hasSyncFramework; + + // The offset in nanoseconds to use when VsyncController timestamps present fence + // signaling time. + static int64_t dispSyncPresentTimeOffset; + + // Some hardware can do RGB->YUV conversion more efficiently in hardware + // controlled by HWC than in hardware controlled by the video encoder. + // This instruct VirtualDisplaySurface to use HWC for such conversion on + // GL composition. + static bool useHwcForRgbToYuv; + + // Controls the number of buffers SurfaceFlinger will allocate for use in + // FramebufferSurface + static int64_t maxFrameBufferAcquiredBuffers; + + // Controls the minimum acquired buffers SurfaceFlinger will suggest via + // ISurfaceComposer.getMaxAcquiredBufferCount(). + static int64_t minAcquiredBuffers; + + // Controls the maximum width and height in pixels that the graphics pipeline can support for + // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs. + static uint32_t maxGraphicsWidth; + static uint32_t maxGraphicsHeight; + // Indicate if device wants color management on its display. static const constexpr bool useColorManagement = true; + static bool useContextPriority; + + // The data space and pixel format that SurfaceFlinger expects hardware composer + // to composite efficiently. Meaning under most scenarios, hardware composer + // will accept layers with the data space and pixel format. + static ui::Dataspace defaultCompositionDataspace; + static ui::PixelFormat defaultCompositionPixelFormat; + + // The data space and pixel format that SurfaceFlinger expects hardware composer + // to composite efficiently for wide color gamut surfaces. Meaning under most scenarios, + // hardware composer will accept layers with the data space and pixel format. + static ui::Dataspace wideColorGamutCompositionDataspace; + static ui::PixelFormat wideColorGamutCompositionPixelFormat; + + static constexpr SkipInitializationTag SkipInitialization; + static LatchUnsignaledConfig enableLatchUnsignaledConfig; // must be called before clients can connect @@ -231,8 +275,7 @@ public: // Schedule sampling independently from commit or composite. void scheduleSample(); - const surfaceflinger::Config& getConfig() { return *mConfig; } - surfaceflinger::Factory& getFactory() { return *mConfig->factory; } + surfaceflinger::Factory& getFactory() { return mFactory; } // The CompositionEngine encapsulates all composition related interfaces and actions. compositionengine::CompositionEngine& getCompositionEngine() const; @@ -264,6 +307,10 @@ public: return mTransactionCallbackInvoker; } + // If set, disables reusing client composition buffers. This can be set by + // debug.sf.disable_client_composition_cache + bool mDisableClientCompositionCache = false; + // Disables expensive rendering for all displays // This is scheduled on the main thread void disableExpensiveRendering(); @@ -274,6 +321,17 @@ public: // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect. bool mPredictCompositionStrategy = false; + // If true, then any layer with a SMPTE 170M transfer function is decoded using the sRGB + // transfer instead. This is mainly to preserve legacy behavior, where implementations treated + // SMPTE 170M as sRGB prior to color management being implemented, and now implementations rely + // on this behavior to increase contrast for some media sources. + bool mTreat170mAsSrgb = false; + + // Allows to ignore physical orientation provided through hwc API in favour of + // 'ro.surface_flinger.primary_display_orientation'. + // TODO(b/246793311): Clean up a temporary property + bool mIgnoreHwcPhysicalDisplayOrientation = false; + void forceFutureUpdate(int delayInMs); const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack) REQUIRES(mStateLock, kMainThreadContext); @@ -608,6 +666,12 @@ private: // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to // make calls to sys prop each time. bool mKernelIdleTimerEnabled = false; + // Show spinner with refresh rate overlay + bool mRefreshRateOverlaySpinner = false; + // Show render rate with refresh rate overlay + bool mRefreshRateOverlayRenderRate = false; + // Show render rate overlay offseted to the middle of the screen (e.g. for circular displays) + bool mRefreshRateOverlayShowInMiddle = false; void setDesiredActiveMode(display::DisplayModeRequest&&, bool force = false) REQUIRES(mStateLock); @@ -1042,8 +1106,8 @@ private: */ const std::unordered_map& getGenericLayerMetadataKeyMap() const; - int calculateMaxAcquiredBufferCount(Fps refreshRate, - std::chrono::nanoseconds presentLatency) const; + static int calculateMaxAcquiredBufferCount(Fps refreshRate, + std::chrono::nanoseconds presentLatency); int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const; bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const; @@ -1053,7 +1117,8 @@ private: void traverseLegacyLayers(const LayerVector::Visitor& visitor) const; sp mStartPropertySetThread; - surfaceflinger::Config* const mConfig = nullptr; + surfaceflinger::Factory& mFactory; + pid_t mPid; std::future mRenderEnginePrimeCacheFuture; // mStateLock has conventions related to the current thread, because only @@ -1080,6 +1145,12 @@ private: float mGlobalSaturationFactor = 1.0f; mat4 mClientColorMatrix; + size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS; + // If there are more GraphicBufferProducers tracked by SurfaceFlinger than + // this threshold, then begin logging. + size_t mGraphicBufferProducerListSizeLogThreshold = + static_cast(0.95 * static_cast(MAX_LAYERS)); + // protected by mStateLock (but we could use another lock) bool mLayersRemoved = false; bool mLayersAdded = false; @@ -1089,6 +1160,7 @@ private: // constant members (no synchronization needed for access) const nsecs_t mBootTime = systemTime(); + bool mIsUserBuild = true; // Can only accessed from the main thread, these members // don't need synchronization @@ -1100,6 +1172,7 @@ private: // Used to ensure we omit a callback when HDR layer info listener is newly added but the // scene hasn't changed bool mAddingHDRLayerInfoListener = false; + bool mIgnoreHdrCameraLayers = false; // Set during transaction application stage to track if the input info or children // for a layer has changed. @@ -1158,6 +1231,9 @@ private: std::atomic mDebugInTransaction = 0; std::atomic_bool mForceFullDamage = false; + bool mLayerCachingEnabled = false; + bool mBackpressureGpuComposition = false; + LayerTracing mLayerTracing; bool mLayerTracingEnabled = false; @@ -1170,6 +1246,9 @@ private: VsyncId mLastCommittedVsyncId; + // If blurs should be enabled on this device. + bool mSupportsBlur = false; + TransactionCallbackInvoker mTransactionCallbackInvoker; // We maintain a pool of pre-generated texture names to hand out to avoid @@ -1201,9 +1280,13 @@ private: // This property can be used to force SurfaceFlinger to always pick a certain color mode. ui::ColorMode mForceColorMode = ui::ColorMode::NATIVE; - std::optional mOverrideDefaultCompositionDataspace; - std::optional mOverrideWideColorGamutCompositionDataspace; + // Whether to enable wide color gamut (e.g. Display P3) for internal displays that support it. + // If false, wide color modes are filtered out for all internal displays. + bool mSupportsWideColor = false; + ui::Dataspace mDefaultCompositionDataspace; + ui::Dataspace mWideColorGamutCompositionDataspace; + ui::Dataspace mColorSpaceAgnosticDataspace; float mDimmingRatio = -1.f; std::unique_ptr mRenderEngine; @@ -1217,6 +1300,8 @@ private: // any mutex. size_t mMaxRenderTargetSize{1}; + const std::string mHwcServiceName; + /* * Scheduler */ @@ -1233,9 +1318,14 @@ private: // below flags are set by main thread only bool mSetActiveModePending = false; + bool mLumaSampling = true; sp mRegionSamplingThread; sp mFpsReporter; sp mTunnelModeEnabledReporter; + ui::DisplayPrimaries mInternalDisplayPrimaries; + + const float mEmulatedDisplayDensity; + const float mInternalDisplayDensity; // Should only be accessed by the main thread. sp mInputFlinger; @@ -1312,6 +1402,9 @@ private: bool mPowerHintSessionEnabled; + bool mLayerLifecycleManagerEnabled = false; + bool mLegacyFrontEndEnabled = true; + frontend::LayerLifecycleManager mLayerLifecycleManager; frontend::LayerHierarchyBuilder mLayerHierarchyBuilder{{}}; frontend::LayerSnapshotBuilder mLayerSnapshotBuilder; diff --git a/services/surfaceflinger/SurfaceFlingerConfig.cpp b/services/surfaceflinger/SurfaceFlingerConfig.cpp deleted file mode 100644 index 0b25a4462d..0000000000 --- a/services/surfaceflinger/SurfaceFlingerConfig.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include "SurfaceFlingerConfig.h" - -namespace android::surfaceflinger { - -using namespace std::string_literals; - -namespace { - -// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity. -constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; - -float getDensityFromProperty(const std::string& key, bool required) { - std::string value = base::GetProperty(key, ""s); - const float density = static_cast(std::atof(value.c_str())); - if (density == 0.f && required) { - ALOGE("%s must be defined as a build property", key.c_str()); - return FALLBACK_DENSITY; - } - return density; -} - -} // namespace - -Config::Config() = default; - -Config Config::makeDefault(Factory* factory) { - Config cfg{}; - - // Note: The values set here will affect tests. - // To keep tests hermetic, do not set values here based on runtime values. - - cfg.factory = factory; - cfg.hwcServiceName = "default"s; - cfg.pid = getpid(); // Exception to the hermetic rules. Allow the pid to be cached. - - return cfg; -} - -Config Config::makeProduction(Factory* factory) { - Config cfg = makeDefault(factory); - - cfg.hwcServiceName = base::GetProperty("debug.sf.hwc_service_name"s, "default"s); - - cfg.emulatedDisplayDensity = getDensityFromProperty("qemu.sf.lcd_density"s, false), - cfg.internalDisplayDensity = - getDensityFromProperty("ro.sf.lcd_density"s, cfg.emulatedDisplayDensity == 0.f), - - cfg.hasSyncFramework = sysprop::running_without_sync_framework(cfg.hasSyncFramework); - cfg.dispSyncPresentTimeOffset = - sysprop::present_time_offset_from_vsync_ns(cfg.dispSyncPresentTimeOffset); - cfg.useHwcForRgbToYuv = sysprop::force_hwc_copy_for_virtual_displays(cfg.useHwcForRgbToYuv); - cfg.maxFrameBufferAcquiredBuffers = - sysprop::max_frame_buffer_acquired_buffers(cfg.maxFrameBufferAcquiredBuffers); - cfg.minAcquiredBuffers = sysprop::SurfaceFlingerProperties::min_acquired_buffers().value_or( - cfg.minAcquiredBuffers); - - cfg.maxGraphicsWidth = std::max(static_cast(sysprop::max_graphics_width( - static_cast(cfg.maxGraphicsWidth))), - 0u); - cfg.maxGraphicsHeight = std::max(static_cast(sysprop::max_graphics_height( - static_cast(cfg.maxGraphicsHeight))), - 0u); - - cfg.supportsWideColor = sysprop::has_wide_color_display(cfg.supportsWideColor); - - cfg.defaultCompositionDataspace = static_cast( - sysprop::default_composition_dataspace(cfg.defaultCompositionDataspace)); - cfg.defaultCompositionPixelFormat = static_cast( - sysprop::default_composition_pixel_format(cfg.defaultCompositionPixelFormat)); - - cfg.wideColorGamutCompositionDataspace = - static_cast(sysprop::wcg_composition_dataspace( - cfg.supportsWideColor ? ui::Dataspace::DISPLAY_P3 : ui::Dataspace::V0_SRGB)); - cfg.wideColorGamutCompositionPixelFormat = static_cast( - sysprop::wcg_composition_pixel_format(cfg.wideColorGamutCompositionPixelFormat)); - - cfg.colorSpaceAgnosticDataspace = static_cast( - sysprop::color_space_agnostic_dataspace(cfg.colorSpaceAgnosticDataspace)); - - cfg.internalDisplayPrimaries = sysprop::getDisplayNativePrimaries(); - - cfg.layerCachingEnabled = - base::GetBoolProperty("debug.sf.enable_layer_caching"s, - android::sysprop::SurfaceFlingerProperties::enable_layer_caching() - .value_or(cfg.layerCachingEnabled)); - cfg.useContextPriority = sysprop::use_context_priority(cfg.useContextPriority); - - cfg.isUserBuild = "user"s == base::GetProperty("ro.build.type"s, "user"s); - - cfg.backpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, - cfg.backpressureGpuComposition); - cfg.supportsBlur = - base::GetBoolProperty("ro.surface_flinger.supports_background_blur"s, cfg.supportsBlur); - - cfg.lumaSampling = base::GetBoolProperty("debug.sf.luma_sampling"s, cfg.lumaSampling); - - cfg.disableClientCompositionCache = - base::GetBoolProperty("debug.sf.disable_client_composition_cache"s, - cfg.disableClientCompositionCache); - - cfg.predictCompositionStrategy = - base::GetBoolProperty("debug.sf.predict_hwc_composition_strategy"s, - cfg.predictCompositionStrategy); - - cfg.treat170mAsSrgb = - base::GetBoolProperty("debug.sf.treat_170m_as_sRGB"s, cfg.treat170mAsSrgb); - - cfg.ignoreHwcPhysicalDisplayOrientation = - base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, - cfg.ignoreHwcPhysicalDisplayOrientation); - - cfg.trebleTestingOverride = - base::GetBoolProperty("debug.sf.treble_testing_override"s, cfg.trebleTestingOverride); - - // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner - cfg.refreshRateOverlay.showSpinner = - base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_spinner"s, - cfg.refreshRateOverlay.showSpinner); - cfg.refreshRateOverlay.showRenderRate = - base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_render_rate"s, - cfg.refreshRateOverlay.showRenderRate); - cfg.refreshRateOverlay.showInMiddle = - base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_in_middle"s, - cfg.refreshRateOverlay.showInMiddle); - - cfg.ignoreHdrCameraLayers = sysprop::ignore_hdr_camera_layers(cfg.ignoreHdrCameraLayers); - - cfg.enableTransactionTracing = base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, - cfg.enableTransactionTracing); - cfg.layerLifecycleManagerEnabled = - base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, - cfg.layerLifecycleManagerEnabled); - cfg.legacyFrontEndEnabled = !cfg.layerLifecycleManagerEnabled || - base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false); - - return cfg; -} - -} // namespace android::surfaceflinger \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlingerConfig.h b/services/surfaceflinger/SurfaceFlingerConfig.h deleted file mode 100644 index 7c3348e3bd..0000000000 --- a/services/surfaceflinger/SurfaceFlingerConfig.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include -#include - -namespace android::surfaceflinger { - -class Factory; - -struct Config final { - Factory* factory = nullptr; - - std::string hwcServiceName; - pid_t pid; - - float emulatedDisplayDensity = 0; - float internalDisplayDensity = 0; - - // If fences from sync Framework are supported. - bool hasSyncFramework = true; - - // The offset in nanoseconds to use when VsyncController timestamps present - // fence signaling time. - int64_t dispSyncPresentTimeOffset = 0; - - // Some hardware can do RGB->YUV conversion more efficiently in hardware - // controlled by HWC than in hardware controlled by the video encoder. This - // instruct VirtualDisplaySurface to use HWC for such conversion on GL - // composition. - bool useHwcForRgbToYuv = false; - - // Controls the number of buffers SurfaceFlinger will allocate for use in - // FramebufferSurface - int64_t maxFrameBufferAcquiredBuffers = 2; - - // Controls the minimum acquired buffers SurfaceFlinger will suggest via - // ISurfaceComposer.getMaxAcquiredBufferCount(). - int64_t minAcquiredBuffers = 1; - - // Controls the maximum width and height in pixels that the graphics - // pipeline can support for GPU fallback composition. For example, 8k - // devices with 4k GPUs, or 4k devices with 2k GPUs. - uint32_t maxGraphicsWidth = 0; - uint32_t maxGraphicsHeight = 0; - - // Whether to enable wide color gamut (e.g. Display P3) for internal - // displays that support it. If false, wide color modes are filtered out - // for all internal displays. - bool mSupportsWideColor = false; - bool supportsWideColor = false; - - // The data space and pixel format that SurfaceFlinger expects hardware - // composer to composite efficiently. Meaning under most scenarios, - // hardware composer will accept layers with the data space and pixel - // format. - ui::Dataspace defaultCompositionDataspace = ui::Dataspace::V0_SRGB; - ui::PixelFormat defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888; - - // The data space and pixel format that SurfaceFlinger expects hardware - // composer to composite efficiently for wide color gamut surfaces. Meaning - // under most scenarios, hardware composer will accept layers with the data - // space and pixel format. - ui::Dataspace wideColorGamutCompositionDataspace = ui::Dataspace::V0_SRGB; - ui::PixelFormat wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; - - ui::Dataspace colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN; - - ui::DisplayPrimaries internalDisplayPrimaries{}; - - bool layerCachingEnabled = false; - bool useContextPriority = true; - bool isUserBuild = true; - bool backpressureGpuComposition = true; - - // If blurs should be enabled on this device. - bool supportsBlur = false; - bool lumaSampling = true; - - // If set, disables reusing client composition buffers. This can be set by - // debug.sf.disable_client_composition_cache - bool disableClientCompositionCache = false; - - // If set, composition engine tries to predict the composition strategy - // provided by HWC based on the previous frame. If the strategy can be - // predicted, gpu composition will run parallel to the hwc validateDisplay - // call and re-run if the predition is incorrect. - bool predictCompositionStrategy = true; - - // If true, then any layer with a SMPTE 170M transfer function is decoded - // using the sRGB transfer instead. This is mainly to preserve legacy - // behavior, where implementations treated SMPTE 170M as sRGB prior to - // color management being implemented, and now implementations rely on this - // behavior to increase contrast for some media sources. - bool treat170mAsSrgb = false; - - // Allows to ignore physical orientation provided through hwc API in favour - // of 'ro.surface_flinger.primary_display_orientation'. - // TODO(b/246793311): Clean up a temporary property - bool ignoreHwcPhysicalDisplayOrientation = false; - - bool trebleTestingOverride = false; - - struct { - // Show spinner with refresh rate overlay - bool showSpinner = false; - - // Show render rate with refresh rate overlay - bool showRenderRate = false; - - // Show render rate overlay offseted to the middle of the screen (e.g. - // for circular displays) - bool showInMiddle = false; - } refreshRateOverlay; - - bool ignoreHdrCameraLayers = false; - bool enableTransactionTracing = true; - bool layerLifecycleManagerEnabled = false; - bool legacyFrontEndEnabled = true; - - static Config makeDefault(Factory* factory); - static Config makeProduction(Factory* factory); - -private: - Config(); -}; - -} // namespace android::surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp index ac351cb1d7..7bd6cf69f3 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp @@ -14,17 +14,22 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "SurfaceFlinger.h" -#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerDefaultFactory.h" namespace android::surfaceflinger { sp createSurfaceFlinger() { static DefaultFactory factory; - static Config config = Config::makeProduction(&factory); - return sp::make(config); + return sp::make(factory); } } // namespace android::surfaceflinger + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp index d296c47237..9fac14ed4c 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp @@ -481,8 +481,7 @@ void DisplayHardwareFuzzer::invokeFrameBufferSurface() { sp surface = sp::make(mHwc, mPhysicalDisplayId, bqConsumer, - getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/, - mFdp.PickValueInArray(kMaxFrameBufferAcquiredBuffers)); + getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/); surface->beginFrame(mFdp.ConsumeBool()); surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes)); @@ -516,8 +515,7 @@ void DisplayHardwareFuzzer::invokeVirtualDisplaySurface() { auto surface = sp::make(mHwc, VirtualDisplayId, sink, bqProducer, bqConsumer, - mFdp.ConsumeRandomLengthString().c_str() /*name*/, - mFdp.ConsumeBool() /* useHwcForRgbToYuv */); + mFdp.ConsumeRandomLengthString().c_str() /*name*/); surface->beginFrame(mFdp.ConsumeBool()); surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes)); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp index df342dcd8e..80943b5b63 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp @@ -124,20 +124,19 @@ void SurfaceFlingerFuzzer::invokeFlinger() { mFlinger->setSchedFifo(mFdp.ConsumeBool()); mFlinger->setSchedAttr(mFdp.ConsumeBool()); mFlinger->getServiceName(); - - auto& config = mTestableFlinger.mutableConfig(); - config.hasSyncFramework = mFdp.ConsumeBool(); - config.dispSyncPresentTimeOffset = mFdp.ConsumeIntegral(); - config.useHwcForRgbToYuv = mFdp.ConsumeBool(); - config.maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral(); - config.maxGraphicsWidth = mFdp.ConsumeIntegral(); - config.maxGraphicsHeight = mFdp.ConsumeIntegral(); - config.supportsWideColor = mFdp.ConsumeBool(); - config.useContextPriority = mFdp.ConsumeBool(); - config.defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces); - config.defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); - config.wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces); - config.wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); + mFlinger->hasSyncFramework = mFdp.ConsumeBool(); + mFlinger->dispSyncPresentTimeOffset = mFdp.ConsumeIntegral(); + mFlinger->useHwcForRgbToYuv = mFdp.ConsumeBool(); + mFlinger->maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral(); + mFlinger->maxGraphicsWidth = mFdp.ConsumeIntegral(); + mFlinger->maxGraphicsHeight = mFdp.ConsumeIntegral(); + mTestableFlinger.mutableSupportsWideColor() = mFdp.ConsumeBool(); + mFlinger->useContextPriority = mFdp.ConsumeBool(); + + mFlinger->defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces); + mFlinger->defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); + mFlinger->wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces); + mFlinger->wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats); mFlinger->enableLatchUnsignaledConfig = mFdp.PickValueInArray(kLatchUnsignaledConfig); @@ -156,7 +155,7 @@ void SurfaceFlingerFuzzer::invokeFlinger() { } void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() { - auto& primaries = mTestableFlinger.mutableConfig().internalDisplayPrimaries; + ui::DisplayPrimaries primaries; primaries.red.X = mFdp.ConsumeFloatingPoint(); primaries.red.Y = mFdp.ConsumeFloatingPoint(); primaries.red.Z = mFdp.ConsumeFloatingPoint(); @@ -169,6 +168,7 @@ void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() { primaries.white.X = mFdp.ConsumeFloatingPoint(); primaries.white.Y = mFdp.ConsumeFloatingPoint(); primaries.white.Z = mFdp.ConsumeFloatingPoint(); + mTestableFlinger.setInternalDisplayPrimaries(primaries); } void SurfaceFlingerFuzzer::setTransactionState() { diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 97cb5d35e3..0c9a16bee3 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -46,7 +46,6 @@ #include "Scheduler/VsyncModulator.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" -#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerDefaultFactory.h" #include "ThreadContext.h" #include "TimeStats/TimeStats.h" @@ -151,8 +150,6 @@ static constexpr ui::PixelFormat kPixelFormats[] = {ui::PixelFormat::RGBA_8888, ui::PixelFormat::YCBCR_P010, ui::PixelFormat::HSV_888}; -static constexpr int kMaxFrameBufferAcquiredBuffers[] = {2, 3, 4}; - inline VsyncId getFuzzedVsyncId(FuzzedDataProvider& fdp) { return VsyncId{fdp.ConsumeIntegral()}; } @@ -407,8 +404,6 @@ public: SurfaceFlinger *flinger() { return mFlinger.get(); } scheduler::TestableScheduler *scheduler() { return mScheduler; } - auto& mutableConfig() { return mConfig; } - void initializeDisplays() { FTL_FAKE_GUARD(kMainThreadContext, mFlinger->initializeDisplays()); } @@ -700,6 +695,10 @@ public: mFactory.mCreateNativeWindowSurface = f; } + void setInternalDisplayPrimaries(const ui::DisplayPrimaries &primaries) { + memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries)); + } + static auto &mutableLayerDrawingState(const sp &layer) { return layer->mDrawingState; } auto &mutableStateLock() { return mFlinger->mStateLock; } @@ -765,12 +764,13 @@ public: auto calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) const { - return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency); + return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } /* Read-write access to private data to set up preconditions and assert * post-conditions. */ + auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplays() { return mFlinger->mDisplays; } auto& mutableDrawingState() { return mFlinger->mDrawingState; } @@ -794,8 +794,8 @@ private: void triggerOnFrameRateOverridesChanged() override {} surfaceflinger::test::Factory mFactory; - surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory); - sp mFlinger = sp::make(mConfig); + sp mFlinger = + sp::make(mFactory, SurfaceFlinger::SkipInitialization); scheduler::TestableScheduler *mScheduler = nullptr; std::shared_ptr mRefreshRateSelector; }; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp index c16a005f0d..849a896ce2 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp @@ -17,15 +17,13 @@ #include #include "SurfaceFlinger.h" -#include "SurfaceFlingerConfig.h" #include "SurfaceFlingerDefaultFactory.h" using namespace android; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { DefaultFactory factory; - surfaceflinger::Config config = surfaceflinger::Config::makeDefault(&factory); - sp flinger = sp::make(config); + sp flinger = sp::make(factory); flinger->init(); sp composerAIDL = sp::make(flinger); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 7124f879e9..e32cf8863b 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -34,7 +34,7 @@ DisplayTransactionTest::DisplayTransactionTest(bool withMockScheduler) { ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - mFlinger.mutableConfig().supportsWideColor = false; + mFlinger.mutableSupportsWideColor() = false; mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; mFlinger.setCreateBufferQueueFunction([](auto, auto, auto) { diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index 5599a7a600..ee12276994 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -684,7 +684,7 @@ struct WideColorNotSupportedVariant { static constexpr bool WIDE_COLOR_SUPPORTED = false; static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableConfig().supportsWideColor = true; + test->mFlinger.mutableSupportsWideColor() = true; } static void setupComposerCallExpectations(DisplayTransactionTest* test) { @@ -699,7 +699,7 @@ struct WideColorSupportNotConfiguredVariant { static constexpr bool WIDE_COLOR_SUPPORTED = false; static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableConfig().supportsWideColor = false; + test->mFlinger.mutableSupportsWideColor() = false; test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 6c14f6e1c1..fab3c0e887 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -250,8 +250,10 @@ TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); - mFlinger.mutableConfig().minAcquiredBuffers = 2; + const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers(); + mFlinger.mutableMinAcquiredBuffers() = 2; EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms)); + mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers; } MATCHER(Is120Hz, "") { diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp index fe383846d1..5951c9893f 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp @@ -84,7 +84,9 @@ TEST_F(GetDisplayNativePrimaries, internalDisplayWithPrimariesData) { injector.inject(); auto internalDisplayToken = injector.token(); - populateDummyDisplayNativePrimaries(mFlinger.mutableConfig().internalDisplayPrimaries); + ui::DisplayPrimaries expectedPrimaries; + populateDummyDisplayNativePrimaries(expectedPrimaries); + mFlinger.setInternalDisplayPrimaries(expectedPrimaries); ui::DisplayPrimaries primaries; EXPECT_EQ(NO_ERROR, mFlinger.getDisplayNativePrimaries(internalDisplayToken, primaries)); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp index 61891c14c7..c0796df6cb 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp @@ -36,7 +36,7 @@ struct WideColorP3ColorimetricSupportedVariant { static constexpr bool WIDE_COLOR_SUPPORTED = true; static void injectConfigChange(DisplayTransactionTest* test) { - test->mFlinger.mutableConfig().supportsWideColor = true; + test->mFlinger.mutableSupportsWideColor() = true; test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 099abf59b4..156c40a721 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -45,8 +45,6 @@ #include "Scheduler/RefreshRateSelector.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" -#include "SurfaceFlingerConfig.h" -#include "SurfaceFlingerDefaultFactory.h" #include "TestableScheduler.h" #include "mock/DisplayHardware/MockComposer.h" #include "mock/DisplayHardware/MockDisplayMode.h" @@ -170,15 +168,13 @@ public: TestableSurfaceFlinger(sp flinger = nullptr) : mFlinger(flinger) { if (!mFlinger) { - mFlinger = sp::make(mConfig); + mFlinger = sp::make(mFactory, SurfaceFlinger::SkipInitialization); } } SurfaceFlinger* flinger() { return mFlinger.get(); } scheduler::TestableScheduler* scheduler() { return mScheduler; } - auto& mutableConfig() { return mConfig; } - // Extend this as needed for accessing SurfaceFlinger private (and public) // functions. @@ -316,6 +312,10 @@ public: mFactory.mCreateNativeWindowSurface = f; } + void setInternalDisplayPrimaries(const ui::DisplayPrimaries& primaries) { + memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries)); + } + static auto& mutableLayerDrawingState(const sp& layer) { return layer->mDrawingState; } auto& mutableStateLock() { return mFlinger->mStateLock; } @@ -513,7 +513,7 @@ public: auto calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) const { - return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency); + return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } auto setDesiredDisplayModeSpecs(const sp& displayToken, @@ -596,6 +596,8 @@ public: const auto& hwcPhysicalDisplayIdMap() const { return getHwComposer().mPhysicalDisplayIdMap; } const auto& hwcDisplayData() const { return getHwComposer().mDisplayData; } + auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; } + auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } auto& mutableDisplays() { return mFlinger->mDisplays; } @@ -620,6 +622,8 @@ public: return SurfaceFlinger::sActiveDisplayRotationFlags; } + auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; } + auto fromHandle(const sp& handle) { return LayerHandle::getLayer(handle); } ~TestableSurfaceFlinger() { @@ -1004,7 +1008,6 @@ private: static constexpr VsyncId kVsyncId{123}; surfaceflinger::test::Factory mFactory; - surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory); sp mFlinger; scheduler::mock::SchedulerCallback mSchedulerCallback; scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback; -- cgit v1.2.3-59-g8ed1b From 3cc15a4f1d6cf72afbb4d883e038ebf9108c78a9 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 30 Jun 2023 06:20:22 +0000 Subject: [sf] add debug dump for new front end Test: window type populated correctly in sf dump Test: dumpsys SurfaceFlinger Bug: 238781169 Change-Id: I86e475393c8b157496862fa34420c13fc80d681c --- .../surfaceflinger/FrontEnd/LayerHierarchy.cpp | 32 +++++-- services/surfaceflinger/FrontEnd/LayerHierarchy.h | 9 +- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 92 ++++++++++++++++++- services/surfaceflinger/FrontEnd/LayerSnapshot.h | 3 +- .../FrontEnd/RequestedLayerState.cpp | 17 ++++ .../surfaceflinger/FrontEnd/RequestedLayerState.h | 2 + services/surfaceflinger/Layer.cpp | 58 +++++++++++- services/surfaceflinger/Layer.h | 9 +- services/surfaceflinger/SurfaceFlinger.cpp | 102 +++++++++++++++++---- services/surfaceflinger/SurfaceFlinger.h | 3 +- 10 files changed, 296 insertions(+), 31 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 163d34575c..ab4c15d670 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -149,13 +149,33 @@ std::string LayerHierarchy::getDebugStringShort() const { return debug + "}"; } -std::string LayerHierarchy::getDebugString(const char* prefix) const { - std::string debug = prefix + getDebugStringShort(); - for (auto& [child, childVariant] : mChildren) { - std::string childPrefix = " " + std::string(prefix) + " " + std::to_string(childVariant); - debug += "\n" + child->getDebugString(childPrefix.c_str()); +void LayerHierarchy::dump(std::ostream& out, const std::string& prefix, + LayerHierarchy::Variant variant, bool isLastChild) const { + if (!mLayer) { + out << " ROOT"; + } else { + out << prefix + (isLastChild ? "└─ " : "├─ "); + if (variant == LayerHierarchy::Variant::Relative) { + out << "(Relative) "; + } else if (variant == LayerHierarchy::Variant::Mirror) { + out << "(Mirroring) " << *mLayer << "\n" + prefix + " └─ ..."; + return; + } + out << *mLayer; } - return debug; + + for (size_t i = 0; i < mChildren.size(); i++) { + auto& [child, childVariant] = mChildren[i]; + if (childVariant == LayerHierarchy::Variant::Detached) continue; + const bool lastChild = i == (mChildren.size() - 1); + std::string childPrefix = prefix; + if (mLayer) { + childPrefix += (isLastChild ? " " : "│ "); + } + out << "\n"; + child->dump(out, childPrefix, childVariant, lastChild); + } + return; } bool LayerHierarchy::hasRelZLoop(uint32_t& outInvalidRelativeRoot) const { diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index 5389adab6a..1e4838727b 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -156,7 +156,12 @@ public: const RequestedLayerState* getLayer() const; const LayerHierarchy* getRelativeParent() const; const LayerHierarchy* getParent() const; - std::string getDebugString(const char* prefix = "") const; + friend std::ostream& operator<<(std::ostream& os, const LayerHierarchy& obj) { + std::string prefix = " "; + obj.dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false); + return os; + } + std::string getDebugStringShort() const; // Traverse the hierarchy and return true if loops are found. The outInvalidRelativeRoot // will contain the first relative root that was visited twice in a traversal. @@ -172,6 +177,8 @@ private: void updateChild(LayerHierarchy*, LayerHierarchy::Variant); void traverseInZOrder(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const; void traverse(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const; + void dump(std::ostream& out, const std::string& prefix, LayerHierarchy::Variant variant, + bool isLastChild) const; const RequestedLayerState* mLayer; LayerHierarchy* mParent = nullptr; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index f0826c6db3..6f68a92e66 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -39,6 +39,63 @@ void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFram } } +std::ostream& operator<<(std::ostream& os, const ui::Transform& transform) { + const uint32_t type = transform.getType(); + const uint32_t orientation = transform.getOrientation(); + if (type == ui::Transform::IDENTITY) { + return os; + } + + if (type & ui::Transform::UNKNOWN) { + std::string out; + transform.dump(out, "", ""); + os << out; + return os; + } + + if (type & ui::Transform::ROTATE) { + switch (orientation) { + case ui::Transform::ROT_0: + os << "ROT_0"; + break; + case ui::Transform::FLIP_H: + os << "FLIP_H"; + break; + case ui::Transform::FLIP_V: + os << "FLIP_V"; + break; + case ui::Transform::ROT_90: + os << "ROT_90"; + break; + case ui::Transform::ROT_180: + os << "ROT_180"; + break; + case ui::Transform::ROT_270: + os << "ROT_270"; + break; + case ui::Transform::ROT_INVALID: + default: + os << "ROT_INVALID"; + break; + } + } + + if (type & ui::Transform::SCALE) { + std::string out; + android::base::StringAppendF(&out, " scale x=%.4f y=%.4f ", transform.getScaleX(), + transform.getScaleY()); + os << out; + } + + if (type & ui::Transform::TRANSLATE) { + std::string out; + android::base::StringAppendF(&out, " tx=%.4f ty=%.4f ", transform.tx(), transform.ty()); + os << out; + } + + return os; +} + } // namespace LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, @@ -59,6 +116,7 @@ LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, } sequence = static_cast(state.id); name = state.name; + debugName = state.debugName; textureName = state.textureName; premultipliedAlpha = state.premultipliedAlpha; inputInfo.name = state.name; @@ -180,13 +238,13 @@ std::string LayerSnapshot::getIsVisibleReason() const { if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot"; if (invalidTransform) return "invalidTransform"; if (color.a == 0.0f && !hasBlur()) return "alpha = 0 and no blur"; - if (!hasSomethingToDraw()) return "!hasSomethingToDraw"; + if (!hasSomethingToDraw()) return "nothing to draw"; // visible std::stringstream reason; if (sidebandStream != nullptr) reason << " sidebandStream"; if (externalTexture != nullptr) - reason << " buffer:" << externalTexture->getId() << " frame:" << frameNumber; + reason << " buffer=" << externalTexture->getId() << " frame=" << frameNumber; if (fillsColor() || color.a > 0.0f) reason << " color{" << color << "}"; if (drawShadows()) reason << " shadowSettings.length=" << shadowSettings.length; if (backgroundBlurRadius > 0) reason << " backgroundBlurRadius=" << backgroundBlurRadius; @@ -232,6 +290,36 @@ std::string LayerSnapshot::getDebugString() const { return debug.str(); } +std::ostream& operator<<(std::ostream& out, const LayerSnapshot& obj) { + out << "Layer [" << obj.path.id; + if (obj.path.mirrorRootId != UNASSIGNED_LAYER_ID) { + out << " mirrored from " << obj.path.mirrorRootId; + } + out << "] " << obj.name << "\n " << (obj.isVisible ? "visible" : "invisible") + << " reason=" << obj.getIsVisibleReason(); + + if (!obj.geomLayerBounds.isEmpty()) { + out << "\n bounds={" << obj.transformedBounds.left << "," << obj.transformedBounds.top + << "," << obj.transformedBounds.bottom << "," << obj.transformedBounds.right << "}"; + } + + if (obj.geomLayerTransform.getType() != ui::Transform::IDENTITY) { + out << " toDisplayTransform={" << obj.geomLayerTransform << "}"; + } + + if (obj.hasInputInfo()) { + out << "\n input{" + << "(" << obj.inputInfo.inputConfig.string() << ")"; + if (obj.touchCropId != UNASSIGNED_LAYER_ID) out << " touchCropId=" << obj.touchCropId; + if (obj.inputInfo.replaceTouchableRegionWithCrop) out << " replaceTouchableRegionWithCrop"; + auto touchableRegion = obj.inputInfo.touchableRegion.getBounds(); + out << " touchableRegion={" << touchableRegion.left << "," << touchableRegion.top << "," + << touchableRegion.bottom << "," << touchableRegion.right << "}" + << "}"; + } + return out; +} + FloatRect LayerSnapshot::sourceBounds() const { if (!externalTexture) { return geomLayerBounds; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index 2f45d52162..9f0822c4ac 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -67,6 +67,7 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { // generated from the same layer, for example when mirroring. int32_t sequence; std::string name; + std::string debugName; uint32_t textureName; bool contentOpaque; bool layerOpaqueFlagSet; @@ -145,7 +146,7 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { bool hasInputInfo() const; FloatRect sourceBounds() const; Hwc2::IComposerClient::BlendMode getBlendMode(const RequestedLayerState& requested) const; - + friend std::ostream& operator<<(std::ostream& os, const LayerSnapshot& obj); void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges, bool forceFullDamage, uint32_t displayRotationFlags); }; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 065b8956c5..a4777d1148 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -127,6 +127,16 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) gameMode = gui::GameMode::Unsupported; requestedFrameRate = {}; cachingHint = gui::CachingHint::Enabled; + + if (name.length() > 77) { + std::string shortened; + shortened.append(name, 0, 36); + shortened.append("[...]"); + shortened.append(name, name.length() - 36); + debugName = std::move(shortened); + } else { + debugName = name; + } } void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerState) { @@ -371,6 +381,13 @@ std::string RequestedLayerState::getDebugString() const { return debug.str(); } +std::ostream& operator<<(std::ostream& out, const RequestedLayerState& obj) { + out << obj.debugName; + if (obj.relativeParentId != UNASSIGNED_LAYER_ID) out << " parent=" << obj.parentId; + if (!obj.handleAlive) out << " handleNotAlive"; + return out; +} + std::string RequestedLayerState::getDebugStringShort() const { return "[" + std::to_string(id) + "]" + name; } diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h index 8ca1cd6323..1c19d6d5fc 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h @@ -74,6 +74,7 @@ struct RequestedLayerState : layer_state_t { Rect getBufferCrop() const; std::string getDebugString() const; std::string getDebugStringShort() const; + friend std::ostream& operator<<(std::ostream& os, const RequestedLayerState& obj); aidl::android::hardware::graphics::composer3::Composition getCompositionType() const; bool hasValidRelativeParent() const; bool hasInputInfo() const; @@ -118,6 +119,7 @@ struct RequestedLayerState : layer_state_t { uint32_t bgColorLayerId = UNASSIGNED_LAYER_ID; uint64_t barrierFrameNumber = 0; uint32_t barrierProducerId = 0; + std::string debugName; // book keeping states bool handleAlive = true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5a010e8af6..a430074e9c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -402,7 +402,7 @@ void Layer::updateTrustedPresentationState(const DisplayDevice* display, mLastComputedTrustedPresentationState = false; if (!leaveState) { - const auto outputLayer = findOutputLayerForDisplay(display); + const auto outputLayer = findOutputLayerForDisplay(display, snapshot->path); if (outputLayer != nullptr) { if (outputLayer->getState().coveredRegionExcludingDisplayOverlays) { Region coveredRegion = @@ -741,6 +741,11 @@ const char* Layer::getDebugName() const { aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType( const DisplayDevice& display) const { const auto outputLayer = findOutputLayerForDisplay(&display); + return getCompositionType(outputLayer); +} + +aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType( + const compositionengine::OutputLayer* outputLayer) const { if (outputLayer == nullptr) { return aidl::android::hardware::graphics::composer3::Composition::INVALID; } @@ -1611,7 +1616,7 @@ void Layer::miniDumpHeader(std::string& result) { result.append("\n"); } -void Layer::miniDump(std::string& result, const DisplayDevice& display) const { +void Layer::miniDumpLegacy(std::string& result, const DisplayDevice& display) const { const auto outputLayer = findOutputLayerForDisplay(&display); if (!outputLayer) { return; @@ -1662,6 +1667,41 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { result.append("\n"); } +void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapshot, + const DisplayDevice& display) const { + const auto outputLayer = findOutputLayerForDisplay(&display, snapshot.path); + if (!outputLayer) { + return; + } + + StringAppendF(&result, " %s\n", snapshot.debugName.c_str()); + StringAppendF(&result, " %10zu | ", snapshot.globalZ); + StringAppendF(&result, " %10d | ", + snapshot.layerMetadata.getInt32(gui::METADATA_WINDOW_TYPE, 0)); + StringAppendF(&result, "%10s | ", toString(getCompositionType(outputLayer)).c_str()); + const auto& outputLayerState = outputLayer->getState(); + StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str()); + const Rect& frame = outputLayerState.displayFrame; + StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); + const FloatRect& crop = outputLayerState.sourceCrop; + StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, + crop.bottom); + const auto frameRate = snapshot.frameRate; + if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) { + StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(), + ftl::enum_string(frameRate.type).c_str(), + ftl::enum_string(frameRate.seamlessness).c_str()); + } else { + result.append(41, ' '); + } + + const auto focused = isLayerFocusedBasedOnPriority(snapshot.frameRateSelectionPriority); + StringAppendF(&result, " [%s]\n", focused ? "*" : " "); + + result.append(kDumpTableRowLength, '-'); + result.append("\n"); +} + void Layer::dumpFrameStats(std::string& result) const { mFrameTracker.dumpStats(result); } @@ -2578,6 +2618,20 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE); } +compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( + const DisplayDevice* display, const frontend::LayerHierarchy::TraversalPath& path) const { + if (!display) return nullptr; + sp layerFE; + for (auto& [p, layer] : mLayerFEs) { + if (p == path) { + layerFE = layer; + } + } + + if (!layerFE) return nullptr; + return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE); +} + Region Layer::getVisibleRegion(const DisplayDevice* display) const { const auto outputLayer = findOutputLayerForDisplay(display); return outputLayer ? outputLayer->getState().visibleRegion : Region(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 2fbbbdcb5c..5d77657415 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -343,6 +343,7 @@ public: virtual sp getCompositionEngineLayerFE() const; virtual sp copyCompositionEngineLayerFE() const; sp getCompositionEngineLayerFE(const frontend::LayerHierarchy::TraversalPath&); + sp getOrCreateCompositionEngineLayerFE(const frontend::LayerHierarchy::TraversalPath&); const frontend::LayerSnapshot* getLayerSnapshot() const; frontend::LayerSnapshot* editLayerSnapshot(); @@ -692,7 +693,8 @@ public: gui::LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const; - void miniDump(std::string& result, const DisplayDevice&) const; + void miniDumpLegacy(std::string& result, const DisplayDevice&) const; + void miniDump(std::string& result, const frontend::LayerSnapshot&, const DisplayDevice&) const; void dumpFrameStats(std::string& result) const; void dumpOffscreenDebugInfo(std::string& result) const; void clearFrameStats(); @@ -960,6 +962,8 @@ protected: void addZOrderRelative(const wp& relative); void removeZOrderRelative(const wp& relative); compositionengine::OutputLayer* findOutputLayerForDisplay(const DisplayDevice*) const; + compositionengine::OutputLayer* findOutputLayerForDisplay( + const DisplayDevice*, const frontend::LayerHierarchy::TraversalPath& path) const; bool usingRelativeZ(LayerVector::StateSet) const; virtual ui::Transform getInputTransform() const; @@ -1064,7 +1068,8 @@ private: aidl::android::hardware::graphics::composer3::Composition getCompositionType( const DisplayDevice&) const; - + aidl::android::hardware::graphics::composer3::Composition getCompositionType( + const compositionengine::OutputLayer*) const; /** * Returns an unsorted vector of all layers that are part of this tree. * That includes the current layer and all its descendants. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 927a826cba..c17ba73824 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5735,7 +5735,7 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)}, {"--events"s, dumper(&SurfaceFlinger::dumpEvents)}, {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)}, - {"--hwclayers"s, dumper(&SurfaceFlinger::dumpHwcLayersMinidumpLocked)}, + {"--hwclayers"s, dumper(&SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, @@ -5753,17 +5753,56 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { // traversals, which can result in use-after-frees. std::string compositionLayers; mScheduler - ->schedule([&] { - StringAppendF(&compositionLayers, "Composition layers\n"); - mDrawingState.traverseInZOrder([&](Layer* layer) { - auto* compositionState = layer->getCompositionState(); - if (!compositionState || !compositionState->isVisible) return; - - android::base::StringAppendF(&compositionLayers, "* Layer %p (%s)\n", layer, - layer->getDebugName() ? layer->getDebugName() - : ""); - compositionState->dump(compositionLayers); - }); + ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { + if (!mLayerLifecycleManagerEnabled) { + StringAppendF(&compositionLayers, "Composition layers\n"); + mDrawingState.traverseInZOrder([&](Layer* layer) { + auto* compositionState = layer->getCompositionState(); + if (!compositionState || !compositionState->isVisible) return; + android::base::StringAppendF(&compositionLayers, "* Layer %p (%s)\n", + layer, + layer->getDebugName() + ? layer->getDebugName() + : ""); + compositionState->dump(compositionLayers); + }); + } else { + std::ostringstream out; + out << "\nComposition list\n"; + ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; + mLayerSnapshotBuilder.forEachVisibleSnapshot( + [&](std::unique_ptr& snapshot) { + if (snapshot->hasSomethingToDraw()) { + if (lastPrintedLayerStackHeader != + snapshot->outputFilter.layerStack) { + lastPrintedLayerStackHeader = + snapshot->outputFilter.layerStack; + out << "LayerStack=" << lastPrintedLayerStackHeader.id + << "\n"; + } + out << " " << *snapshot << "\n"; + } + }); + + out << "\nInput list\n"; + lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; + mLayerSnapshotBuilder.forEachInputSnapshot( + [&](const frontend::LayerSnapshot& snapshot) { + if (lastPrintedLayerStackHeader != + snapshot.outputFilter.layerStack) { + lastPrintedLayerStackHeader = + snapshot.outputFilter.layerStack; + out << "LayerStack=" << lastPrintedLayerStackHeader.id + << "\n"; + } + out << " " << snapshot << "\n"; + }); + + out << "\nLayer Hierarchy\n" + << mLayerHierarchyBuilder.getHierarchy() << "\n\n"; + compositionLayers = out.str(); + dumpHwcLayersMinidump(compositionLayers); + } }) .get(); @@ -6093,7 +6132,7 @@ void SurfaceFlinger::dumpOffscreenLayers(std::string& result) { result.append(future.get()); } -void SurfaceFlinger::dumpHwcLayersMinidumpLocked(std::string& result) const { +void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const { for (const auto& [token, display] : mDisplays) { const auto displayId = HalDisplayId::tryCast(display->getId()); if (!displayId) { @@ -6105,7 +6144,33 @@ void SurfaceFlinger::dumpHwcLayersMinidumpLocked(std::string& result) const { Layer::miniDumpHeader(result); const DisplayDevice& ref = *display; - mDrawingState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, ref); }); + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->miniDumpLegacy(result, ref); }); + result.append("\n"); + } +} + +void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { + for (const auto& [token, display] : mDisplays) { + const auto displayId = HalDisplayId::tryCast(display->getId()); + if (!displayId) { + continue; + } + + StringAppendF(&result, "Display %s (%s) HWC layers:\n", to_string(*displayId).c_str(), + displayId == mActiveDisplayId ? "active" : "inactive"); + 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); + LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s", + snapshot.getDebugString().c_str()); + it->second->miniDump(result, snapshot, ref); + }); result.append("\n"); } } @@ -6154,7 +6219,10 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp * Dump the visible layer list */ colorizer.bold(result); - StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers.load()); + StringAppendF(&result, "SurfaceFlinger New Frontend Enabled:%s\n", + mLayerLifecycleManagerEnabled ? "true" : "false"); + StringAppendF(&result, "Active Layers - layers with client handles (count = %zu)\n", + mNumLayers.load()); colorizer.reset(result); result.append(compositionLayers); @@ -6227,7 +6295,9 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp } result.push_back('\n'); - dumpHwcLayersMinidumpLocked(result); + if (mLegacyFrontEndEnabled) { + dumpHwcLayersMinidumpLockedLegacy(result); + } { DumpArgs plannerArgs; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5c57abdb32..d97a7478dd 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1049,7 +1049,8 @@ private: */ void dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers, std::string& result) const REQUIRES(mStateLock); - void dumpHwcLayersMinidumpLocked(std::string& result) const REQUIRES(mStateLock); + void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext); + void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock); void appendSfConfigString(std::string& result) const; void listLayersLocked(std::string& result) const; -- cgit v1.2.3-59-g8ed1b From e9ee0003a7324aeffdcab5e8f6d8ed19198ad9b2 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Sat, 1 Jul 2023 03:14:51 +0000 Subject: Revert "[sf] enable new sf frontend" This reverts commit a5d3d28952a66de3a8c5629ca6a6678e88e92b47. Reason for revert: b/289421905 Change-Id: I86b9677b8a1d73f70f04247a7a0c66314411b867 --- services/surfaceflinger/Layer.cpp | 4 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a430074e9c..3a41f1599b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2621,6 +2621,10 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( const DisplayDevice* display, const frontend::LayerHierarchy::TraversalPath& path) const { if (!display) return nullptr; + if (!mFlinger->mLayerLifecycleManagerEnabled) { + return display->getCompositionDisplay()->getOutputLayerForLayer( + getCompositionEngineLayerFE()); + } sp layerFE; for (auto& [p, layer] : mLayerFEs) { if (p == path) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 116ef37e07..c46da11a03 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -487,7 +487,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false); mLayerLifecycleManagerEnabled = - base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, true); + base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, false); mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled || base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false); } -- cgit v1.2.3-59-g8ed1b From c638470eccb89b0ec9594f968d9ccc07c5a6854b Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 31 Jul 2023 12:22:20 -0700 Subject: [sf] respect parent alpha when calculating blur radius and blur regions Fixes a regression caused by breaking front end and composition engine dependencies. Test: atest BlurTests Bug: 293532283 Change-Id: If9962a46bc7dba3b8f4256ae23307094a9c93290 --- services/surfaceflinger/Layer.cpp | 8 ++++---- services/surfaceflinger/LayerFE.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3a41f1599b..1a0517ac0d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -594,8 +594,8 @@ void Layer::prepareBasicGeometryCompositionState() { snapshot->localTransformInverse = snapshot->localTransform.inverse(); snapshot->blendMode = static_cast(blendMode); snapshot->alpha = alpha; - snapshot->backgroundBlurRadius = drawingState.backgroundBlurRadius; - snapshot->blurRegions = drawingState.blurRegions; + snapshot->backgroundBlurRadius = getBackgroundBlurRadius(); + snapshot->blurRegions = getBlurRegions(); snapshot->stretchEffect = getStretchEffect(); } @@ -664,8 +664,8 @@ void Layer::preparePerFrameCompositionState() { snapshot->forceClientComposition = true; } // If there are no visible region changes, we still need to update blur parameters. - snapshot->blurRegions = drawingState.blurRegions; - snapshot->backgroundBlurRadius = drawingState.backgroundBlurRadius; + snapshot->blurRegions = getBlurRegions(); + snapshot->backgroundBlurRadius = getBackgroundBlurRadius(); // Layer framerate is used in caching decisions. // Retrieve it from the scheduler which maintains an instance of LayerHistory, and store it in diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index f855f278c3..4d3e04861b 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -16,7 +16,7 @@ // #define LOG_NDEBUG 0 #undef LOG_TAG -#define LOG_TAG "LayerFE" +#define LOG_TAG "SurfaceFlinger" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include -- cgit v1.2.3-59-g8ed1b From 9f64cc89030657b250977e6d0ebeeb5482a4bcda Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Fri, 4 Aug 2023 12:26:30 -0400 Subject: Remove redundant check for blurRegions to force client composition If there are blurRegions on a Layer, we *should* force client composition, but this is already handled in Output::updateCompositionState + Output::findLayerRequestingBackgroundComposition. The check on Layer is redundant, so remove it. Moreover, the check on Layer doesn't do enough. It doesn't handle blur- behind, and it doesn't force the Layers below to use client composition, which is also necessary. This allows us to remove blurs and client composition from protected surfaces on devices that do not have EGL_EXT_protected_content. (See I9763eb22884e611568b36b2e221ee6d75ec3363e.) Bug: 196271643 Test: OutputUpdateAndWriteCompositionStateTest Change-Id: I055d221b1fcb36fb5fbc6747c353d3fb72f4d684 --- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 2 +- services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp | 2 +- services/surfaceflinger/Layer.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index d389a799ad..8f3606667d 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -481,7 +481,7 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate layer_state_t::eApiChanged | layer_state_t::eShadowRadiusChanged | layer_state_t::eBlurRegionsChanged | layer_state_t::eStretchChanged)) { forceClientComposition = isHdrY410 || shadowSettings.length > 0 || - requested.blurRegions.size() > 0 || stretchEffect.hasEffect(); + stretchEffect.hasEffect(); } if (forceUpdate || diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 23cfe928f5..cf39187f0d 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -871,7 +871,7 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a // computed snapshot properties snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 || - requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect(); + snapshot.stretchEffect.hasEffect(); snapshot.contentOpaque = snapshot.isContentOpaque(); snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() && snapshot.color.a == 1.f; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3a41f1599b..83d8d9f81d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -659,8 +659,7 @@ void Layer::preparePerFrameCompositionState() { // Force client composition for special cases known only to the front-end. // Rounded corners no longer force client composition, since we may use a // hole punch so that the layer will appear to have rounded corners. - if (isHdrY410() || drawShadows() || drawingState.blurRegions.size() > 0 || - snapshot->stretchEffect.hasEffect()) { + if (isHdrY410() || drawShadows() || snapshot->stretchEffect.hasEffect()) { snapshot->forceClientComposition = true; } // If there are no visible region changes, we still need to update blur parameters. -- cgit v1.2.3-59-g8ed1b From c1dbfcb35a5b2720afb3e5135ad6f7850159422d Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Mon, 21 Mar 2022 16:48:10 -0400 Subject: Avoid blurring and rounded corners without EGL_EXT_protected_content If the GPU does not support protected content, avoid forcing client composition for protected layers. This means removing rounded corners. It also means avoiding blurring when it would require blurring a layer with protected content. Bug: 196271643 Test: manual (Netflix, YouTube, ExoDefault) with modified RenderEngine::supportsProtectedContent() Change-Id: I9763eb22884e611568b36b2e221ee6d75ec3363e --- services/surfaceflinger/CompositionEngine/src/Output.cpp | 8 +++++++- services/surfaceflinger/Layer.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index d4230f5575..0b11e747ca 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -895,13 +895,19 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const { compositionengine::OutputLayer* layerRequestingBgComposition = nullptr; for (auto* layer : getOutputLayersOrderedByZ()) { - auto* compState = layer->getLayerFE().getCompositionState(); + const auto* compState = layer->getLayerFE().getCompositionState(); // If any layer has a sideband stream, we will disable blurs. In that case, we don't // want to force client composition because of the blur. if (compState->sidebandStream != nullptr) { return nullptr; } + + // If RenderEngine cannot render protected content, we cannot blur. + if (compState->hasProtectedContent && + !getCompositionEngine().getRenderEngine().supportsProtectedContent()) { + return nullptr; + } if (compState->isOpaque) { continue; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 83d8d9f81d..6c9311370e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2110,6 +2110,13 @@ const std::vector Layer::getBlurRegions() const { } RoundedCornerState Layer::getRoundedCornerState() const { + // Today's DPUs cannot do rounded corners. If RenderEngine cannot render + // protected content, remove rounded corners from protected content so it + // can be rendered by the DPU. + if (isProtected() && !mFlinger->getRenderEngine().supportsProtectedContent()) { + return {}; + } + // Get parent settings RoundedCornerState parentSettings; const auto& parent = mDrawingParent.promote(); -- cgit v1.2.3-59-g8ed1b From 994761f2ddc1b266158f72ef3d15c153bceeb9f1 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 4 Aug 2023 21:50:55 +0000 Subject: Remove Y410 fields from SurfaceFlinger Ever since RenderEngine started to use skia this was never used. It will have been three releases since then, so finish cleaning this up. Bug: 130025362 Test: builds Change-Id: Ib0328903e04d754e08b6960949898b282e3d529b --- libs/renderengine/gl/GLESRenderEngine.cpp | 6 ---- libs/renderengine/gl/GLESRenderEngine.h | 1 - libs/renderengine/gl/ProgramCache.cpp | 32 +++------------------- libs/renderengine/gl/ProgramCache.h | 6 ---- .../include/renderengine/LayerSettings.h | 7 +---- .../include/renderengine/private/Description.h | 3 -- .../src/ClientCompositionRequestCache.cpp | 3 +- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 12 +------- services/surfaceflinger/FrontEnd/LayerSnapshot.h | 1 - .../FrontEnd/LayerSnapshotBuilder.cpp | 4 +-- services/surfaceflinger/Layer.cpp | 10 +------ services/surfaceflinger/Layer.h | 2 -- services/surfaceflinger/LayerFE.cpp | 1 - .../tests/unittests/CompositionTest.cpp | 1 - 14 files changed, 10 insertions(+), 79 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 0d7df101f4..e7a2c7a411 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1251,7 +1251,6 @@ void GLESRenderEngine::drawLayersInternal( texture.setFiltering(layer.source.buffer.useTextureFiltering); texture.setDimensions(gBuf->getWidth(), gBuf->getHeight()); - setSourceY410BT2020(layer.source.buffer.isY410BT2020); renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray()); texCoords[0] = vec2(0.0, 0.0); @@ -1294,7 +1293,6 @@ void GLESRenderEngine::drawLayersInternal( // Cleanup if there's a buffer source if (layer.source.buffer.buffer != nullptr) { disableBlending(); - setSourceY410BT2020(false); disableTexturing(); } } @@ -1357,10 +1355,6 @@ void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, } } -void GLESRenderEngine::setSourceY410BT2020(bool enable) { - mState.isY410BT2020 = enable; -} - void GLESRenderEngine::setSourceDataSpace(Dataspace source) { mDataSpace = source; } diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 402ff529d7..ea75e215cd 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -183,7 +183,6 @@ private: void setupCornerRadiusCropSize(float width, float height); // HDR and color management related functions and state - void setSourceY410BT2020(bool enable); void setSourceDataSpace(ui::Dataspace source); void setOutputDataSpace(ui::Dataspace dataspace); void setDisplayMaxLuminance(const float maxLuminance); diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp index f7f2d54515..812dda04fa 100644 --- a/libs/renderengine/gl/ProgramCache.cpp +++ b/libs/renderengine/gl/ProgramCache.cpp @@ -98,9 +98,6 @@ void ProgramCache::primeCache( shaderKey.set(Key::INPUT_TF_MASK, (i & 1) ? Key::INPUT_TF_HLG : Key::INPUT_TF_ST2084); - // Cache Y410 input on or off - shaderKey.set(Key::Y410_BT2020_MASK, (i & 2) ? - Key::Y410_BT2020_ON : Key::Y410_BT2020_OFF); if (cache.count(shaderKey) == 0) { cache.emplace(shaderKey, generateProgram(shaderKey)); shaderCount++; @@ -161,13 +158,11 @@ void ProgramCache::primeCache( ProgramCache::Key ProgramCache::computeKey(const Description& description) { Key needs; needs.set(Key::TEXTURE_MASK, - !description.textureEnabled - ? Key::TEXTURE_OFF + !description.textureEnabled ? Key::TEXTURE_OFF : description.texture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES - ? Key::TEXTURE_EXT - : description.texture.getTextureTarget() == GL_TEXTURE_2D - ? Key::TEXTURE_2D - : Key::TEXTURE_OFF) + ? Key::TEXTURE_EXT + : description.texture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_2D + : Key::TEXTURE_OFF) .set(Key::ALPHA_MASK, (description.color.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE) .set(Key::BLEND_MASK, description.isPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL) @@ -186,8 +181,6 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) { .set(Key::ROUNDED_CORNERS_MASK, description.cornerRadius > 0 ? Key::ROUNDED_CORNERS_ON : Key::ROUNDED_CORNERS_OFF) .set(Key::SHADOW_MASK, description.drawShadows ? Key::SHADOW_ON : Key::SHADOW_OFF); - needs.set(Key::Y410_BT2020_MASK, - description.isY410BT2020 ? Key::Y410_BT2020_ON : Key::Y410_BT2020_OFF); if (needs.hasTransformMatrix() || (description.inputTransferFunction != description.outputTransferFunction)) { @@ -650,20 +643,6 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { fs << "uniform vec4 color;"; } - if (needs.isY410BT2020()) { - fs << R"__SHADER__( - vec3 convertY410BT2020(const vec3 color) { - const vec3 offset = vec3(0.0625, 0.5, 0.5); - const mat3 transform = mat3( - vec3(1.1678, 1.1678, 1.1678), - vec3( 0.0, -0.1878, 2.1481), - vec3(1.6836, -0.6523, 0.0)); - // Y is in G, U is in R, and V is in B - return clamp(transform * (color.grb - offset), 0.0, 1.0); - } - )__SHADER__"; - } - if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF()) || needs.hasDisplayColorMatrix()) { if (needs.needsToneMapping()) { @@ -730,9 +709,6 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } else { if (needs.isTexturing()) { fs << "gl_FragColor = texture2D(sampler, outTexCoords);"; - if (needs.isY410BT2020()) { - fs << "gl_FragColor.rgb = convertY410BT2020(gl_FragColor.rgb);"; - } } else { fs << "gl_FragColor.rgb = color.rgb;"; fs << "gl_FragColor.a = 1.0;"; diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h index 535d21cd52..b18914fd5e 100644 --- a/libs/renderengine/gl/ProgramCache.h +++ b/libs/renderengine/gl/ProgramCache.h @@ -108,11 +108,6 @@ public: OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT, OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT, - Y410_BT2020_SHIFT = 12, - Y410_BT2020_MASK = 1 << Y410_BT2020_SHIFT, - Y410_BT2020_OFF = 0 << Y410_BT2020_SHIFT, - Y410_BT2020_ON = 1 << Y410_BT2020_SHIFT, - SHADOW_SHIFT = 13, SHADOW_MASK = 1 << SHADOW_SHIFT, SHADOW_OFF = 0 << SHADOW_SHIFT, @@ -180,7 +175,6 @@ public: outputTF >>= Key::OUTPUT_TF_SHIFT; return inputTF != outputTF; } - inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; } // for use by std::unordered_map diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index b3a617c04b..b501c4074b 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -64,9 +64,6 @@ struct Buffer { // overrides the alpha channel of the buffer. bool isOpaque = false; - // HDR color-space setting for Y410. - bool isY410BT2020 = false; - float maxLuminanceNits = 0.0; }; @@ -189,8 +186,7 @@ static inline bool operator==(const Buffer& lhs, const Buffer& rhs) { lhs.useTextureFiltering == rhs.useTextureFiltering && lhs.textureTransform == rhs.textureTransform && lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha && - lhs.isOpaque == rhs.isOpaque && lhs.isY410BT2020 == rhs.isY410BT2020 && - lhs.maxLuminanceNits == rhs.maxLuminanceNits; + lhs.isOpaque == rhs.isOpaque && lhs.maxLuminanceNits == rhs.maxLuminanceNits; } static inline bool operator==(const Geometry& lhs, const Geometry& rhs) { @@ -247,7 +243,6 @@ static inline void PrintTo(const Buffer& settings, ::std::ostream* os) { PrintMatrix(settings.textureTransform, os); *os << "\n .usePremultipliedAlpha = " << settings.usePremultipliedAlpha; *os << "\n .isOpaque = " << settings.isOpaque; - *os << "\n .isY410BT2020 = " << settings.isY410BT2020; *os << "\n .maxLuminanceNits = " << settings.maxLuminanceNits; *os << "\n}"; } diff --git a/libs/renderengine/include/renderengine/private/Description.h b/libs/renderengine/include/renderengine/private/Description.h index fa6ec10b6e..2873ad7148 100644 --- a/libs/renderengine/include/renderengine/private/Description.h +++ b/libs/renderengine/include/renderengine/private/Description.h @@ -64,9 +64,6 @@ struct Description { // color used when texturing is disabled or when setting alpha. half4 color; - // true if the sampled pixel values are in Y410/BT2020 rather than RGBA - bool isY410BT2020 = false; - // transfer functions for the input/output TransferFunction inputTransferFunction = TransferFunction::LINEAR; TransferFunction outputTransferFunction = TransferFunction::LINEAR; diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp index 7e020ee1c1..752257b810 100644 --- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp +++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp @@ -45,8 +45,7 @@ inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const rendereng lhs.useTextureFiltering == rhs.useTextureFiltering && lhs.textureTransform == rhs.textureTransform && lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha && - lhs.isOpaque == rhs.isOpaque && lhs.isY410BT2020 == rhs.isY410BT2020 && - lhs.maxLuminanceNits == rhs.maxLuminanceNits; + lhs.isOpaque == rhs.isOpaque && lhs.maxLuminanceNits == rhs.maxLuminanceNits; } inline bool equalIgnoringBuffer(const renderengine::LayerSettings& lhs, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index ee589c3ce8..5d41fddd98 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -465,22 +465,12 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate color.rgb = requested.getColor().rgb; } - if (forceUpdate || - requested.what & - (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged | - layer_state_t::eApiChanged)) { - isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ && - requested.api == NATIVE_WINDOW_API_MEDIA && - requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102; - } - if (forceUpdate || requested.what & (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged | layer_state_t::eApiChanged | layer_state_t::eShadowRadiusChanged | layer_state_t::eBlurRegionsChanged | layer_state_t::eStretchChanged)) { - forceClientComposition = isHdrY410 || shadowSettings.length > 0 || - stretchEffect.hasEffect(); + forceClientComposition = shadowSettings.length > 0 || stretchEffect.hasEffect(); } if (forceUpdate || diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index 19477fa419..92d23e2724 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -72,7 +72,6 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { Rect transformedBoundsWithoutTransparentRegion; renderengine::ShadowSettings shadowSettings; bool premultipliedAlpha; - bool isHdrY410; ui::Transform parentTransform; Rect bufferSize; Rect croppedBufferSize; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index cf39187f0d..162b546426 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -870,8 +870,8 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a } // computed snapshot properties - snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 || - snapshot.stretchEffect.hasEffect(); + snapshot.forceClientComposition = + snapshot.shadowSettings.length > 0 || snapshot.stretchEffect.hasEffect(); snapshot.contentOpaque = snapshot.isContentOpaque(); snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() && snapshot.color.a == 1.f; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cfcc424622..1737bdf04d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -659,7 +659,7 @@ void Layer::preparePerFrameCompositionState() { // Force client composition for special cases known only to the front-end. // Rounded corners no longer force client composition, since we may use a // hole punch so that the layer will appear to have rounded corners. - if (isHdrY410() || drawShadows() || snapshot->stretchEffect.hasEffect()) { + if (drawShadows() || snapshot->stretchEffect.hasEffect()) { snapshot->forceClientComposition = true; } // If there are no visible region changes, we still need to update blur parameters. @@ -3887,13 +3887,6 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const { return true; } -bool Layer::isHdrY410() const { - // pixel format is HDR Y410 masquerading as RGBA_1010102 - return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && - mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && - mBufferInfo.mPixelFormat == HAL_PIXEL_FORMAT_RGBA_1010102); -} - sp Layer::getCompositionEngineLayerFE() const { // There's no need to get a CE Layer if the layer isn't going to draw anything. return hasSomethingToDraw() ? mLegacyLayerFE : nullptr; @@ -4295,7 +4288,6 @@ void Layer::updateSnapshot(bool updateGeometry) { snapshot->contentOpaque = isOpaque(mDrawingState); snapshot->layerOpaqueFlagSet = (mDrawingState.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque; - snapshot->isHdrY410 = isHdrY410(); sp p = mDrawingParent.promote(); if (p != nullptr) { snapshot->parentTransform = p->getTransform(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5d77657415..25a684500b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -431,8 +431,6 @@ public: void updateCloneBufferInfo(); uint64_t mPreviousFrameNumber = 0; - bool isHdrY410() const; - /* * called after composition. * returns true if the layer latched a new buffer this frame. diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index 4d3e04861b..5ae52abe7b 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -225,7 +225,6 @@ void LayerFE::prepareBufferStateClientComposition( layerSettings.source.buffer.fence = mSnapshot->acquireFence; layerSettings.source.buffer.textureName = mSnapshot->textureName; layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha; - layerSettings.source.buffer.isY410BT2020 = mSnapshot->isHdrY410; bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086; bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3; float maxLuminance = 0.f; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index e8a9cfe9d7..14fa492576 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -600,7 +600,6 @@ struct BaseLayerProperties { EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName); - EXPECT_EQ(false, layer.source.buffer.isY410BT2020); EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha); EXPECT_EQ(false, layer.source.buffer.isOpaque); EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x); -- cgit v1.2.3-59-g8ed1b From c1d19d7cd16cee779f7984b690fb8629d3a1bb29 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 10 Aug 2023 12:35:11 -0700 Subject: [sf] Add bufferless surfaceframe to frametime in new fe Bug: 238781169 Test: presubmit Test: crystall ball perftests via forrest Change-Id: Ic8cae03e732e41de26d7a530ef06b902b064056c --- services/surfaceflinger/Layer.cpp | 4 ++-- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 1 + .../tests/unittests/FrameRateSelectionPriorityTest.cpp | 3 +-- services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp | 3 +-- .../surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp | 5 +---- .../surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp | 5 +---- 7 files changed, 8 insertions(+), 15 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3a41f1599b..ba6f967908 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -836,12 +836,12 @@ uint32_t Layer::doTransaction(uint32_t flags) { mFlinger->mUpdateInputInfo = true; } - commitTransaction(mDrawingState); + commitTransaction(); return flags; } -void Layer::commitTransaction(State&) { +void Layer::commitTransaction() { // Set the present state for all bufferlessSurfaceFramesTX to Presented. The // bufferSurfaceFrameTX will be presented in latchBuffer. for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5d77657415..2ceea7068c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -912,6 +912,7 @@ public: void setTransformHint(std::optional transformHint) { mTransformHint = transformHint; } + void commitTransaction(); // Keeps track of the previously presented layer stacks. This is used to get // the release fences from the correct displays when we release the last buffer // from the layer. @@ -932,7 +933,6 @@ protected: void preparePerFrameCompositionState(); void preparePerFrameBufferCompositionState(); void preparePerFrameEffectsCompositionState(); - virtual void commitTransaction(State& stateToCommit); void gatherBufferInfo(); void onSurfaceFrameCreated(const std::shared_ptr&); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9de623fff9..8e7aa1a306 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2339,6 +2339,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, if (!mLegacyFrontEndEnabled) { ATRACE_NAME("DisplayCallbackAndStatsUpdates"); applyTransactions(update.transactions, vsyncId); + traverseLegacyLayers([&](Layer* layer) { layer->commitTransaction(); }); const nsecs_t latchTime = systemTime(); bool unused = false; diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp index 1c9aee7443..d30d5b8223 100644 --- a/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp @@ -99,8 +99,7 @@ void RefreshRateSelectionTest::setParent(Layer* child, Layer* parent) { } void RefreshRateSelectionTest::commitTransaction(Layer* layer) { - auto c = layer->getDrawingState(); - layer->commitTransaction(c); + layer->commitTransaction(); } namespace { diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 44ab569bd1..a1e4e25c06 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -85,8 +85,7 @@ void SetFrameRateTest::removeChild(sp layer, sp child) { void SetFrameRateTest::commitTransaction() { for (auto layer : mLayers) { - auto c = layer->getDrawingState(); - layer->commitTransaction(c); + layer->commitTransaction(); } } diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index 764d19be0b..00b5bf0506 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -61,10 +61,7 @@ public: return sp::make(args); } - void commitTransaction(Layer* layer) { - auto c = layer->getDrawingState(); - layer->commitTransaction(c); - } + void commitTransaction(Layer* layer) { layer->commitTransaction(); } TestableSurfaceFlinger mFlinger; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index e2c64917dc..caa265fcd9 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -60,10 +60,7 @@ public: return sp::make(args); } - void commitTransaction(Layer* layer) { - auto c = layer->getDrawingState(); - layer->commitTransaction(c); - } + void commitTransaction(Layer* layer) { layer->commitTransaction(); } TestableSurfaceFlinger mFlinger; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); -- cgit v1.2.3-59-g8ed1b From 7f019199c94d15923704bb0e2896c6147dc38998 Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Tue, 8 Aug 2023 20:39:01 +0000 Subject: Use rect instead of four int frame values for WindowInfo Test: Builds Bug: 290795410 Change-Id: Iff104ad14c5da792f32a68d25145b936f6ea71f6 --- libs/gui/WindowInfo.cpp | 25 +++++++--------------- .../fuzzer/libgui_surfaceComposerClient_fuzzer.cpp | 6 ++---- libs/gui/include/gui/WindowInfo.h | 5 +---- libs/gui/tests/WindowInfo_test.cpp | 10 ++------- .../benchmarks/InputDispatcher_benchmarks.cpp | 5 +---- .../inputflinger/dispatcher/InputDispatcher.cpp | 10 ++++----- .../inputflinger/tests/InputDispatcher_test.cpp | 10 ++------- .../FrontEnd/LayerSnapshotBuilder.cpp | 7 +----- services/surfaceflinger/Layer.cpp | 6 +----- services/surfaceflinger/LayerProtoHelper.cpp | 4 ++-- 10 files changed, 25 insertions(+), 63 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp index 52af9d5114..2eb6bd670d 100644 --- a/libs/gui/WindowInfo.cpp +++ b/libs/gui/WindowInfo.cpp @@ -43,7 +43,7 @@ bool WindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const { } bool WindowInfo::frameContainsPoint(int32_t x, int32_t y) const { - return x >= frameLeft && x < frameRight && y >= frameTop && y < frameBottom; + return x >= frame.left && x < frame.right && y >= frame.top && y < frame.bottom; } bool WindowInfo::supportsSplitTouch() const { @@ -59,18 +59,15 @@ bool WindowInfo::interceptsStylus() const { } bool WindowInfo::overlaps(const WindowInfo* other) const { - const bool nonEmpty = (frameRight - frameLeft > 0) || (frameBottom - frameTop > 0); - return nonEmpty && frameLeft < other->frameRight && frameRight > other->frameLeft && - frameTop < other->frameBottom && frameBottom > other->frameTop; + return !frame.isEmpty() && frame.left < other->frame.right && frame.right > other->frame.left && + frame.top < other->frame.bottom && frame.bottom > other->frame.top; } bool WindowInfo::operator==(const WindowInfo& info) const { return info.token == token && info.id == id && info.name == name && - info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft && - info.frameTop == frameTop && info.frameRight == frameRight && - info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && - info.globalScaleFactor == globalScaleFactor && info.transform == transform && - info.touchableRegion.hasSameRects(touchableRegion) && + info.dispatchingTimeout == dispatchingTimeout && info.frame == frame && + info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && + info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && info.touchOcclusionMode == touchOcclusionMode && info.ownerPid == ownerPid && info.ownerUid == ownerUid && info.packageName == packageName && info.inputConfig == inputConfig && info.displayId == displayId && @@ -103,10 +100,7 @@ status_t WindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt32(layoutParamsFlags.get()) ?: parcel->writeInt32( static_cast>(layoutParamsType)) ?: - parcel->writeInt32(frameLeft) ?: - parcel->writeInt32(frameTop) ?: - parcel->writeInt32(frameRight) ?: - parcel->writeInt32(frameBottom) ?: + parcel->write(frame) ?: parcel->writeInt32(surfaceInset) ?: parcel->writeFloat(globalScaleFactor) ?: parcel->writeFloat(alpha) ?: @@ -155,10 +149,7 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { // clang-format off status = parcel->readInt32(&lpFlags) ?: parcel->readInt32(&lpType) ?: - parcel->readInt32(&frameLeft) ?: - parcel->readInt32(&frameTop) ?: - parcel->readInt32(&frameRight) ?: - parcel->readInt32(&frameBottom) ?: + parcel->read(frame) ?: parcel->readInt32(&surfaceInset) ?: parcel->readFloat(&globalScaleFactor) ?: parcel->readFloat(&alpha) ?: diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp index 3e37e4850e..4daa3be36f 100644 --- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp +++ b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp @@ -178,10 +178,8 @@ void SurfaceComposerClientFuzzer::getWindowInfo(gui::WindowInfo* windowInfo) { windowInfo->name = mFdp.ConsumeRandomLengthString(kRandomStringMaxBytes); windowInfo->layoutParamsFlags = mFdp.PickValueInArray(kFlags); windowInfo->layoutParamsType = mFdp.PickValueInArray(kType); - windowInfo->frameLeft = mFdp.ConsumeIntegral(); - windowInfo->frameTop = mFdp.ConsumeIntegral(); - windowInfo->frameRight = mFdp.ConsumeIntegral(); - windowInfo->frameBottom = mFdp.ConsumeIntegral(); + windowInfo->frame = Rect(mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral(), + mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral()); windowInfo->surfaceInset = mFdp.ConsumeIntegral(); windowInfo->alpha = mFdp.ConsumeFloatingPointInRange(0, 1); ui::Transform transform(mFdp.PickValueInArray(kOrientation)); diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index 7ff73874ae..bd2eb7413b 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -194,10 +194,7 @@ struct WindowInfo : public Parcelable { std::chrono::nanoseconds dispatchingTimeout = std::chrono::seconds(5); /* These values are filled in by SurfaceFlinger. */ - int32_t frameLeft = -1; - int32_t frameTop = -1; - int32_t frameRight = -1; - int32_t frameBottom = -1; + Rect frame = Rect::INVALID_RECT; /* * SurfaceFlinger consumes this value to shrink the computed frame. This is diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp index 461fe4a4ce..f2feaefa13 100644 --- a/libs/gui/tests/WindowInfo_test.cpp +++ b/libs/gui/tests/WindowInfo_test.cpp @@ -52,10 +52,7 @@ TEST(WindowInfo, Parcelling) { i.layoutParamsFlags = WindowInfo::Flag::SLIPPERY; i.layoutParamsType = WindowInfo::Type::INPUT_METHOD; i.dispatchingTimeout = 12s; - i.frameLeft = 93; - i.frameTop = 34; - i.frameRight = 16; - i.frameBottom = 19; + i.frame = Rect(93, 34, 16, 19); i.surfaceInset = 17; i.globalScaleFactor = 0.3; i.alpha = 0.7; @@ -85,10 +82,7 @@ TEST(WindowInfo, Parcelling) { ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags); ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType); ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout); - ASSERT_EQ(i.frameLeft, i2.frameLeft); - ASSERT_EQ(i.frameTop, i2.frameTop); - ASSERT_EQ(i.frameRight, i2.frameRight); - ASSERT_EQ(i.frameBottom, i2.frameBottom); + ASSERT_EQ(i.frame, i2.frame); ASSERT_EQ(i.surfaceInset, i2.surfaceInset); ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor); ASSERT_EQ(i.alpha, i2.alpha); diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index 6dd785ae56..188d5f048d 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -185,10 +185,7 @@ public: mInfo.token = mClientChannel->getConnectionToken(); mInfo.name = "FakeWindowHandle"; mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; - mInfo.frameLeft = mFrame.left; - mInfo.frameTop = mFrame.top; - mInfo.frameRight = mFrame.right; - mInfo.frameBottom = mFrame.bottom; + mInfo.frame = mFrame; mInfo.globalScaleFactor = 1.0; mInfo.touchableRegion.clear(); mInfo.addTouchableRegion(mFrame); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 2923a3cfa7..630542fe47 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3011,8 +3011,8 @@ std::string InputDispatcher::dumpWindowForTouchOcclusion(const WindowInfo* info, "hasToken=%s, applicationInfo.name=%s, applicationInfo.token=%s\n", isTouchedWindow ? "[TOUCHED] " : "", info->packageName.c_str(), info->ownerUid.toString().c_str(), info->id, - toString(info->touchOcclusionMode).c_str(), info->alpha, info->frameLeft, - info->frameTop, info->frameRight, info->frameBottom, + toString(info->touchOcclusionMode).c_str(), info->alpha, info->frame.left, + info->frame.top, info->frame.right, info->frame.bottom, dumpRegion(info->touchableRegion).c_str(), info->name.c_str(), info->inputConfig.string().c_str(), toString(info->token != nullptr), info->applicationInfo.name.c_str(), @@ -5644,9 +5644,9 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { i, windowInfo->name.c_str(), windowInfo->id, windowInfo->displayId, windowInfo->inputConfig.string().c_str(), - windowInfo->alpha, windowInfo->frameLeft, - windowInfo->frameTop, windowInfo->frameRight, - windowInfo->frameBottom, windowInfo->globalScaleFactor, + windowInfo->alpha, windowInfo->frame.left, + windowInfo->frame.top, windowInfo->frame.right, + windowInfo->frame.bottom, windowInfo->globalScaleFactor, windowInfo->applicationInfo.name.c_str(), binderToString(windowInfo->applicationInfo.token).c_str()); dump += dumpRegion(windowInfo->touchableRegion); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 6d9cd87c4f..4dd40cda80 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -1131,10 +1131,7 @@ public: mInfo.name = name; mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT; mInfo.alpha = 1.0; - mInfo.frameLeft = 0; - mInfo.frameTop = 0; - mInfo.frameRight = WIDTH; - mInfo.frameBottom = HEIGHT; + mInfo.frame = Rect(0, 0, WIDTH, HEIGHT); mInfo.transform.set(0, 0); mInfo.globalScaleFactor = 1.0; mInfo.touchableRegion.clear(); @@ -1215,10 +1212,7 @@ public: void setApplicationToken(sp token) { mInfo.applicationInfo.token = token; } void setFrame(const Rect& frame, const ui::Transform& displayTransform = ui::Transform()) { - mInfo.frameLeft = frame.left; - mInfo.frameTop = frame.top; - mInfo.frameRight = frame.right; - mInfo.frameBottom = frame.bottom; + mInfo.frame = frame; mInfo.touchableRegion.clear(); mInfo.addTouchableRegion(frame); diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 159d0f028d..30a795f166 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -178,12 +178,7 @@ void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisp info.touchableRegion.clear(); } - const Rect roundedFrameInDisplay = - getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay); - info.frameLeft = roundedFrameInDisplay.left; - info.frameTop = roundedFrameInDisplay.top; - info.frameRight = roundedFrameInDisplay.right; - info.frameBottom = roundedFrameInDisplay.bottom; + info.frame = getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay); ui::Transform inputToLayer; inputToLayer.set(inputBounds.left, inputBounds.top); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 59a8825de5..377ebd4cd1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2398,11 +2398,7 @@ void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& screenToDi info.touchableRegion.clear(); } - const Rect roundedFrameInDisplay = getInputBoundsInDisplaySpace(inputBounds, screenToDisplay); - info.frameLeft = roundedFrameInDisplay.left; - info.frameTop = roundedFrameInDisplay.top; - info.frameRight = roundedFrameInDisplay.right; - info.frameBottom = roundedFrameInDisplay.bottom; + info.frame = getInputBoundsInDisplaySpace(inputBounds, screenToDisplay); ui::Transform inputToLayer; inputToLayer.set(inputBounds.left, inputBounds.top); diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 1c7581b093..341f041086 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -185,8 +185,8 @@ void LayerProtoHelper::writeToProto( static_assert(std::is_same_v); proto->set_layout_params_type(static_cast(inputInfo.layoutParamsType)); - LayerProtoHelper::writeToProto({inputInfo.frameLeft, inputInfo.frameTop, inputInfo.frameRight, - inputInfo.frameBottom}, + LayerProtoHelper::writeToProto({inputInfo.frame.left, inputInfo.frame.top, + inputInfo.frame.right, inputInfo.frame.bottom}, [&]() { return proto->mutable_frame(); }); LayerProtoHelper::writeToProto(inputInfo.touchableRegion, [&]() { return proto->mutable_touchable_region(); }); -- cgit v1.2.3-59-g8ed1b From f6918d4ab8c613302c3eda0b7be15674aceb8610 Mon Sep 17 00:00:00 2001 From: Sally Qi Date: Mon, 7 Aug 2023 15:28:30 -0700 Subject: Refactor `isHdrDataspace` function. - Rename it to `getHdrRenderType` and return a ternary enum. - return the hdr type that we want to treat based on the dataspace, format and hdr/sdr ratio. - pixelformat is optional, in case no source buffer but there is a source color. - hdr/sdr ratio is 1.0f by default, render rengine doesn't take care this param. - The ternary enum has 3 types: just SDR; generic hdr, namely those we need to tonemap; display hdr, namely those self-promoting to HDR by using extended brightness API. Bug: 261485283 Test: HdrRenderTypeUtils_test, TextureViewTest#testSDRFromSurfaceViewAndTextureView, OutputLayerUpdateCompositionStateTest Change-Id: I281687a010bbf5bff555f6fa893002c2a9b324d1 --- libs/renderengine/skia/SkiaRenderEngine.cpp | 9 ++- libs/ui/include_types/ui/DataspaceUtils.h | 29 ---------- libs/ui/include_types/ui/HdrRenderTypeUtils.h | 64 +++++++++++++++++++++ libs/ui/tests/Android.bp | 4 +- libs/ui/tests/DataspaceUtils_test.cpp | 53 ------------------ libs/ui/tests/HdrRenderTypeUtils_test.cpp | 65 ++++++++++++++++++++++ .../CompositionEngine/src/OutputLayer.cpp | 21 +++++-- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 17 +++--- 9 files changed, 162 insertions(+), 102 deletions(-) delete mode 100644 libs/ui/include_types/ui/DataspaceUtils.h create mode 100644 libs/ui/include_types/ui/HdrRenderTypeUtils.h delete mode 100644 libs/ui/tests/DataspaceUtils_test.cpp create mode 100644 libs/ui/tests/HdrRenderTypeUtils_test.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index 29d8ba7267..8ea9ee7478 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -20,7 +20,6 @@ #include "SkiaRenderEngine.h" -#include #include #include #include @@ -55,13 +54,14 @@ #include #include #include +#include #include #include #include #include -#include #include #include +#include #include #include @@ -1027,7 +1027,10 @@ void SkiaRenderEngine::drawLayersInternal( // Most HDR standards require at least 10-bits of color depth for source content, so we // can just extract the transfer function rather than dig into precise gralloc layout. // Furthermore, we can assume that the only 8-bit target we support is RGBA8888. - const bool requiresDownsample = isHdrDataspace(layer.sourceDataspace) && + const bool requiresDownsample = + getHdrRenderType(layer.sourceDataspace, + std::optional(static_cast( + buffer->getPixelFormat()))) != HdrRenderType::SDR && buffer->getPixelFormat() == PIXEL_FORMAT_RGBA_8888; if (layerDimmingRatio <= kDimmingThreshold || requiresDownsample) { paint.setDither(true); diff --git a/libs/ui/include_types/ui/DataspaceUtils.h b/libs/ui/include_types/ui/DataspaceUtils.h deleted file mode 100644 index a461cb4e68..0000000000 --- a/libs/ui/include_types/ui/DataspaceUtils.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -namespace android { - -inline bool isHdrDataspace(ui::Dataspace dataspace) { - const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK; - - return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG; -} - -} // namespace android \ No newline at end of file diff --git a/libs/ui/include_types/ui/HdrRenderTypeUtils.h b/libs/ui/include_types/ui/HdrRenderTypeUtils.h new file mode 100644 index 0000000000..b0af878cdb --- /dev/null +++ b/libs/ui/include_types/ui/HdrRenderTypeUtils.h @@ -0,0 +1,64 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android { + +enum class HdrRenderType { + SDR, // just render to SDR + DISPLAY_HDR, // HDR by extended brightness + GENERIC_HDR // tonemapped HDR +}; + +/*** + * A helper function to classify how we treat the result based on params. + * + * @param dataspace the dataspace + * @param pixelFormat optional, in case there is no source buffer. + * @param hdrSdrRatio default is 1.f, render engine side doesn't take care of it. + * @return HdrRenderType + */ +inline HdrRenderType getHdrRenderType(ui::Dataspace dataspace, + std::optional pixelFormat, + float hdrSdrRatio = 1.f) { + const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK; + const auto range = dataspace & HAL_DATASPACE_RANGE_MASK; + + if (transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG) { + return HdrRenderType::GENERIC_HDR; + } + + static const auto BT2020_LINEAR_EXT = static_cast(HAL_DATASPACE_STANDARD_BT2020 | + HAL_DATASPACE_TRANSFER_LINEAR | + HAL_DATASPACE_RANGE_EXTENDED); + + if ((dataspace == BT2020_LINEAR_EXT || dataspace == ui::Dataspace::V0_SCRGB) && + pixelFormat.has_value() && pixelFormat.value() == ui::PixelFormat::RGBA_FP16) { + return HdrRenderType::GENERIC_HDR; + } + + // Extended range layer with an hdr/sdr ratio of > 1.01f can "self-promote" to HDR. + if (range == HAL_DATASPACE_RANGE_EXTENDED && hdrSdrRatio > 1.01f) { + return HdrRenderType::DISPLAY_HDR; + } + + return HdrRenderType::SDR; +} + +} // namespace android \ No newline at end of file diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 831b64d877..8ce017d7a3 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -164,9 +164,9 @@ cc_test { } cc_test { - name: "DataspaceUtils_test", + name: "HdrRenderTypeUtils_test", shared_libs: ["libui"], - srcs: ["DataspaceUtils_test.cpp"], + srcs: ["HdrRenderTypeUtils_test.cpp"], cflags: [ "-Wall", "-Werror", diff --git a/libs/ui/tests/DataspaceUtils_test.cpp b/libs/ui/tests/DataspaceUtils_test.cpp deleted file mode 100644 index 3e0967182b..0000000000 --- a/libs/ui/tests/DataspaceUtils_test.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#undef LOG_TAG -#define LOG_TAG "DataspaceUtilsTest" - -#include -#include - -namespace android { - -class DataspaceUtilsTest : public testing::Test {}; - -TEST_F(DataspaceUtilsTest, isHdrDataspace) { - EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_ITU_HLG)); - EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_ITU_PQ)); - EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_PQ)); - EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_HLG)); - - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SRGB_LINEAR)); - // scRGB defines a very wide gamut but not an expanded luminance range - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SCRGB_LINEAR)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SRGB)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SCRGB)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_JFIF)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT601_625)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT601_525)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT709)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DCI_P3_LINEAR)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DCI_P3)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_P3_LINEAR)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_P3)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::ADOBE_RGB)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020_LINEAR)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020_ITU)); - EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_BT2020)); -} - -} // namespace android diff --git a/libs/ui/tests/HdrRenderTypeUtils_test.cpp b/libs/ui/tests/HdrRenderTypeUtils_test.cpp new file mode 100644 index 0000000000..efe819db76 --- /dev/null +++ b/libs/ui/tests/HdrRenderTypeUtils_test.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "HdrRenderTypeUtilsTest" + +#include +#include + +namespace android { + +class HdrRenderTypeUtilsTest : public testing::Test {}; + +TEST_F(HdrRenderTypeUtilsTest, getHdrRenderType) { + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_ITU_HLG, std::nullopt), + HdrRenderType::GENERIC_HDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_ITU_PQ, std::nullopt), + HdrRenderType::GENERIC_HDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_PQ, std::nullopt), HdrRenderType::GENERIC_HDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_HLG, std::nullopt), + HdrRenderType::GENERIC_HDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB, + std::optional(ui::PixelFormat::RGBA_FP16)), + HdrRenderType::GENERIC_HDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB, + std::optional(ui::PixelFormat::RGBA_8888), 2.f), + HdrRenderType::DISPLAY_HDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB_LINEAR, + std::optional(ui::PixelFormat::RGBA_8888), 2.f), + HdrRenderType::DISPLAY_HDR); + + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SRGB_LINEAR, std::nullopt), HdrRenderType::SDR); + // scRGB defines a very wide gamut but not an expanded luminance range + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB_LINEAR, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SRGB, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_JFIF, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_BT601_625, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_BT601_525, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_BT709, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::DCI_P3_LINEAR, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::DCI_P3, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::DISPLAY_P3_LINEAR, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::DISPLAY_P3, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::ADOBE_RGB, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_LINEAR, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_ITU, std::nullopt), HdrRenderType::SDR); + EXPECT_EQ(getHdrRenderType(ui::Dataspace::DISPLAY_BT2020, std::nullopt), HdrRenderType::SDR); +} + +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index b492b6a79e..4fe6927d80 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include #include #include @@ -26,7 +25,7 @@ #include #include "system/graphics-base-v1.0.h" -#include +#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -312,15 +311,26 @@ void OutputLayer::updateCompositionState( } } + auto pixelFormat = layerFEState->buffer ? std::make_optional(static_cast( + layerFEState->buffer->getPixelFormat())) + : std::nullopt; + + auto hdrRenderType = + getHdrRenderType(outputState.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio); + // Determine the output dependent dataspace for this layer. If it is // colorspace agnostic, it just uses the dataspace chosen for the output to // avoid the need for color conversion. // For now, also respect the colorspace agnostic flag if we're drawing to HDR, to avoid drastic // luminance shift. TODO(b/292162273): we should check if that's true though. - state.dataspace = layerFEState->isColorspaceAgnostic && !isHdrDataspace(outputState.dataspace) + state.dataspace = layerFEState->isColorspaceAgnostic && hdrRenderType == HdrRenderType::SDR ? outputState.dataspace : layerFEState->dataspace; + // re-get HdrRenderType after the dataspace gets changed. + hdrRenderType = + getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio); + // Override the dataspace transfer from 170M to sRGB if the device configuration requests this. // We do this here instead of in buffer info so that dumpsys can still report layers that are // using the 170M transfer. Also we only do this if the colorspace is not agnostic for the @@ -335,7 +345,7 @@ void OutputLayer::updateCompositionState( // For hdr content, treat the white point as the display brightness - HDR content should not be // boosted or dimmed. // If the layer explicitly requests to disable dimming, then don't dim either. - if (isHdrDataspace(state.dataspace) || + if (hdrRenderType == HdrRenderType::GENERIC_HDR || getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits || getOutput().getState().displayBrightnessNits == 0.f || !layerFEState->dimmingEnabled) { state.dimmingRatio = 1.f; @@ -344,8 +354,7 @@ void OutputLayer::updateCompositionState( float layerBrightnessNits = getOutput().getState().sdrWhitePointNits; // RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular // range that we may need to re-adjust to the current display conditions - if ((state.dataspace & HAL_DATASPACE_RANGE_MASK) == HAL_DATASPACE_RANGE_EXTENDED && - layerFEState->currentHdrSdrRatio > 1.01f) { + if (hdrRenderType == HdrRenderType::DISPLAY_HDR) { layerBrightnessNits *= layerFEState->currentHdrSdrRatio; } state.dimmingRatio = diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 1a0517ac0d..38a36fc6bc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -50,10 +50,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ef483f673d..13a457ed7d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -81,7 +81,6 @@ #include #include #include -#include #include #include #include @@ -89,6 +88,7 @@ #include #include #include +#include #include #include #include @@ -2796,7 +2796,14 @@ bool SurfaceFlinger::isHdrLayer(const frontend::LayerSnapshot& snapshot) const { return false; } } - if (isHdrDataspace(snapshot.dataspace)) { + // RANGE_EXTENDED layer may identify themselves as being "HDR" + // via a desired hdr/sdr ratio + auto pixelFormat = snapshot.buffer + ? std::make_optional(static_cast(snapshot.buffer->getPixelFormat())) + : std::nullopt; + + if (getHdrRenderType(snapshot.dataspace, pixelFormat, snapshot.desiredHdrSdrRatio) != + HdrRenderType::SDR) { return true; } // If the layer is not allowed to be dimmed, treat it as HDR. WindowManager may disable @@ -2806,12 +2813,6 @@ bool SurfaceFlinger::isHdrLayer(const frontend::LayerSnapshot& snapshot) const { if (!snapshot.dimmingEnabled) { return true; } - // RANGE_EXTENDED layers may identify themselves as being "HDR" via a desired sdr/hdr ratio - if ((snapshot.dataspace & (int32_t)Dataspace::RANGE_MASK) == - (int32_t)Dataspace::RANGE_EXTENDED && - snapshot.desiredHdrSdrRatio > 1.01f) { - return true; - } return false; } -- cgit v1.2.3-59-g8ed1b From c3a17824aed485229dba17819e5ee4e4ecf4db1e Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Wed, 16 Aug 2023 14:56:30 +0000 Subject: Delete genTextures and deleteTextures from RenderEngine These methods are no-ops with skia and cause thread bounces in practice so just remove these. Bug: 270628071 Test: builds Change-Id: I0dc549eb7c9a0d94def5a8727322ed49b010ef1f --- .../include/renderengine/LayerSettings.h | 6 --- .../include/renderengine/RenderEngine.h | 3 -- .../include/renderengine/mock/RenderEngine.h | 4 -- libs/renderengine/skia/SkiaRenderEngine.h | 2 - libs/renderengine/tests/RenderEngineTest.cpp | 21 --------- .../renderengine/threaded/RenderEngineThreaded.cpp | 12 ----- libs/renderengine/threaded/RenderEngineThreaded.h | 2 - .../src/ClientCompositionRequestCache.cpp | 3 +- .../surfaceflinger/FrontEnd/LayerCreationArgs.h | 1 - services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 1 - services/surfaceflinger/FrontEnd/LayerSnapshot.h | 1 - .../FrontEnd/RequestedLayerState.cpp | 1 - .../surfaceflinger/FrontEnd/RequestedLayerState.h | 1 - services/surfaceflinger/Layer.cpp | 10 ---- services/surfaceflinger/Layer.h | 2 - services/surfaceflinger/LayerFE.cpp | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 54 ---------------------- services/surfaceflinger/SurfaceFlinger.h | 14 ------ .../fuzzer/surfaceflinger_fuzzer.cpp | 3 -- .../tests/unittests/CompositionTest.cpp | 15 ++---- .../tests/unittests/TestableSurfaceFlinger.h | 1 - 21 files changed, 6 insertions(+), 152 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index b501c4074b..28aa4dd71d 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -46,10 +46,6 @@ struct Buffer { // Fence that will fire when the buffer is ready to be bound. sp fence = nullptr; - // Texture identifier to bind the external texture to. - // TODO(alecmouri): This is GL-specific...make the type backend-agnostic. - uint32_t textureName = 0; - // Whether to use filtering when rendering the texture. bool useTextureFiltering = false; @@ -182,7 +178,6 @@ struct LayerSettings { // compositionengine/impl/ClientCompositionRequestCache.cpp static inline bool operator==(const Buffer& lhs, const Buffer& rhs) { return lhs.buffer == rhs.buffer && lhs.fence == rhs.fence && - lhs.textureName == rhs.textureName && lhs.useTextureFiltering == rhs.useTextureFiltering && lhs.textureTransform == rhs.textureTransform && lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha && @@ -237,7 +232,6 @@ static inline void PrintTo(const Buffer& settings, ::std::ostream* os) { << (settings.buffer.get() ? decodePixelFormat(settings.buffer->getPixelFormat()).c_str() : ""); *os << "\n .fence = " << settings.fence.get(); - *os << "\n .textureName = " << settings.textureName; *os << "\n .useTextureFiltering = " << settings.useTextureFiltering; *os << "\n .textureTransform = "; PrintMatrix(settings.textureTransform, os); diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 72a6075ff1..80aa4c61e6 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -112,9 +112,6 @@ public: // dump the extension strings. always call the base class. virtual void dump(std::string& result) = 0; - virtual void genTextures(size_t count, uint32_t* names) = 0; - virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - // queries that are required to be thread safe virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 571b52b787..78811908d6 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -35,9 +35,6 @@ public: MOCK_METHOD0(primeCache, std::future()); MOCK_METHOD1(dump, void(std::string&)); - MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); - MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); - MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); MOCK_CONST_METHOD0(isProtected, bool()); @@ -53,7 +50,6 @@ public: void(const std::shared_ptr>&&, const DisplaySettings&, const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); - MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); MOCK_METHOD0(supportsBackgroundBlur, bool()); MOCK_METHOD1(onActiveDisplaySizeChanged, void(ui::Size)); diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 011052102d..d4fc959ba5 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -70,8 +70,6 @@ public: void onActiveDisplaySizeChanged(ui::Size size) override final; int reportShadersCompiled(); - virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override final{}; - virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override final{}; virtual void setEnableTracing(bool tracingEnabled) override final; void useProtectedContext(bool useProtectedContext) override; diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 1ad0fa6e70..5eec305096 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -278,9 +278,6 @@ public: if (WRITE_BUFFER_TO_FILE_ON_FAILURE && ::testing::Test::HasFailure()) { writeBufferToFile("/data/texture_out_"); } - for (uint32_t texName : mTexNames) { - mRE->deleteTextures(1, &texName); - } const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); @@ -623,8 +620,6 @@ public: std::unique_ptr mRE; std::shared_ptr mBuffer; - - std::vector mTexNames; }; void RenderEngineTest::initializeRenderEngine() { @@ -668,9 +663,6 @@ struct BufferSourceVariant { static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b, RenderEngineTest* fixture) { const auto buf = fixture->allocateSourceBuffer(1, 1); - uint32_t texName; - fixture->mRE->genTextures(1, &texName); - fixture->mTexNames.push_back(texName); uint8_t* pixels; buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, @@ -690,7 +682,6 @@ struct BufferSourceVariant { buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; - layer.source.buffer.textureName = texName; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; OpaquenessVariant::setOpaqueBit(layer); } @@ -1239,9 +1230,6 @@ void RenderEngineTest::fillRedBufferTextureTransform() { // Here will allocate a checker board texture, but transform texture // coordinates so that only the upper left is applied. const auto buf = allocateSourceBuffer(2, 2); - uint32_t texName; - RenderEngineTest::mRE->genTextures(1, &texName); - this->mTexNames.push_back(texName); uint8_t* pixels; buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, @@ -1262,7 +1250,6 @@ void RenderEngineTest::fillRedBufferTextureTransform() { buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; - layer.source.buffer.textureName = texName; // Transform coordinates to only be inside the red quadrant. layer.source.buffer.textureTransform = mat4::scale(vec4(0.2f, 0.2f, 1.f, 1.f)); layer.alpha = 1.0f; @@ -1288,9 +1275,6 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); - uint32_t texName; - RenderEngineTest::mRE->genTextures(1, &texName); - this->mTexNames.push_back(texName); uint8_t* pixels; buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, @@ -1302,7 +1286,6 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; - layer.source.buffer.textureName = texName; layer.source.buffer.usePremultipliedAlpha = true; layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); @@ -1327,9 +1310,6 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); - uint32_t texName; - RenderEngineTest::mRE->genTextures(1, &texName); - this->mTexNames.push_back(texName); uint8_t* pixels; buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, @@ -1341,7 +1321,6 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; - layer.source.buffer.textureName = texName; layer.source.buffer.usePremultipliedAlpha = false; layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 57055bd9ac..3bc9e6d7e0 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -173,18 +173,6 @@ void RenderEngineThreaded::dump(std::string& result) { result.assign(resultFuture.get()); } -void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) { - ATRACE_CALL(); - // This is a no-op in SkiaRenderEngine. - return; -} - -void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { - ATRACE_CALL(); - // This is a no-op in SkiaRenderEngine. - return; -} - void RenderEngineThreaded::mapExternalTextureBuffer(const sp& buffer, bool isRenderable) { ATRACE_CALL(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 68e50625c8..a7ecab2931 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -46,8 +46,6 @@ public: void dump(std::string& result) override; - void genTextures(size_t count, uint32_t* names) override; - void deleteTextures(size_t count, uint32_t const* names) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp index 752257b810..bdaa1d0ae1 100644 --- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp +++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp @@ -41,8 +41,7 @@ inline bool equalIgnoringSource(const renderengine::LayerSettings& lhs, } inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) { - return lhs.textureName == rhs.textureName && - lhs.useTextureFiltering == rhs.useTextureFiltering && + return lhs.useTextureFiltering == rhs.useTextureFiltering && lhs.textureTransform == rhs.textureTransform && lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha && lhs.isOpaque == rhs.isOpaque && lhs.maxLuminanceNits == rhs.maxLuminanceNits; diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h index c26edb5d22..0788d1abce 100644 --- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h +++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h @@ -54,7 +54,6 @@ struct LayerCreationArgs { gui::LayerMetadata metadata; pid_t ownerPid; uid_t ownerUid; - uint32_t textureName; uint32_t sequence; bool addToRoot = true; wp parentHandle = nullptr; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index d42bce6ed5..80bedf4a39 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -118,7 +118,6 @@ LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, sequence = static_cast(state.id); name = state.name; debugName = state.debugName; - textureName = state.textureName; premultipliedAlpha = state.premultipliedAlpha; inputInfo.name = state.name; inputInfo.id = static_cast(uniqueSequence); diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index 92d23e2724..7537a39060 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -64,7 +64,6 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { int32_t sequence; std::string name; std::string debugName; - uint32_t textureName; bool contentOpaque; bool layerOpaqueFlagSet; RoundedCornerState roundedCorner; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index d979c4662e..a5d556328d 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -51,7 +51,6 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) name(args.name + "#" + std::to_string(args.sequence)), canBeRoot(args.addToRoot), layerCreationFlags(args.flags), - textureName(args.textureName), ownerUid(args.ownerUid), ownerPid(args.ownerPid), parentId(args.parentId), diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h index 030930289d..8eff22bbe4 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h @@ -95,7 +95,6 @@ struct RequestedLayerState : layer_state_t { const std::string name; bool canBeRoot = false; const uint32_t layerCreationFlags; - const uint32_t textureName; // The owner of the layer. If created from a non system process, it will be the calling uid. // If created from a system process, the value can be passed in. const gui::Uid ownerUid; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 59a8825de5..af4b65bcbc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -149,7 +149,6 @@ Layer::Layer(const LayerCreationArgs& args) args.metadata.getInt32(gui::METADATA_WINDOW_TYPE, 0))), mLayerCreationFlags(args.flags), mBorderEnabled(false), - mTextureName(args.textureName), mLegacyLayerFE(args.flinger->getFactory().createLayerFE(mName)) { ALOGV("Creating Layer %s", getDebugName()); @@ -214,7 +213,6 @@ Layer::Layer(const LayerCreationArgs& args) mSnapshot->sequence = sequence; mSnapshot->name = getDebugName(); - mSnapshot->textureName = mTextureName; mSnapshot->premultipliedAlpha = mPremultipliedAlpha; mSnapshot->parentTransform = {}; } @@ -236,13 +234,6 @@ Layer::~Layer() { mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber, mBufferInfo.mFence); } - if (!isClone()) { - // The original layer and the clone layer share the same texture. Therefore, only one of - // the layers, in this case the original layer, needs to handle the deletion. The original - // layer and the clone should be removed at the same time so there shouldn't be any issue - // with the clone layer trying to use the deleted texture. - mFlinger->deleteTextureAsync(mTextureName); - } const int32_t layerId = getSequence(); mFlinger->mTimeStats->onDestroy(layerId); mFlinger->mFrameTracer->onDestroy(layerId); @@ -3624,7 +3615,6 @@ Rect Layer::computeBufferCrop(const State& s) { sp Layer::createClone(uint32_t mirrorRootId) { LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()); - args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->setInitialValuesForClone(sp::fromExisting(this), mirrorRootId); return layer; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index faf0e3c117..8a65d9dba6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1191,8 +1191,6 @@ private: void setTransformHintLegacy(ui::Transform::RotationFlags); void resetDrawingStateBufferInfo(); - const uint32_t mTextureName; - // Transform hint provided to the producer. This must be accessed holding // the mStateLock. ui::Transform::RotationFlags mTransformHintLegacy = ui::Transform::ROT_0; diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index 5ae52abe7b..a0024d52d4 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -223,7 +223,6 @@ void LayerFE::prepareBufferStateClientComposition( layerSettings.source.buffer.buffer = mSnapshot->externalTexture; layerSettings.source.buffer.isOpaque = mSnapshot->contentOpaque; layerSettings.source.buffer.fence = mSnapshot->acquireFence; - layerSettings.source.buffer.textureName = mSnapshot->textureName; layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha; bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086; bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5dd1598299..9e6e934648 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -730,42 +730,6 @@ void SurfaceFlinger::bootFinished() { })); } -uint32_t SurfaceFlinger::getNewTexture() { - { - std::lock_guard lock(mTexturePoolMutex); - if (!mTexturePool.empty()) { - uint32_t name = mTexturePool.back(); - mTexturePool.pop_back(); - ATRACE_INT("TexturePoolSize", mTexturePool.size()); - return name; - } - - // The pool was too small, so increase it for the future - ++mTexturePoolSize; - } - - // The pool was empty, so we need to get a new texture name directly using a - // blocking call to the main thread - auto genTextures = [this] { - uint32_t name = 0; - getRenderEngine().genTextures(1, &name); - return name; - }; - if (std::this_thread::get_id() == mMainThreadId) { - return genTextures(); - } else { - return mScheduler->schedule(genTextures).get(); - } -} - -void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { - std::lock_guard lock(mTexturePoolMutex); - // We don't change the pool size, so the fix-up logic in postComposition will decide whether - // to actually delete this or not based on mTexturePoolSize - mTexturePool.push_back(texture); - ATRACE_INT("TexturePoolSize", mTexturePool.size()); -} - static std::optional chooseRenderEngineTypeViaSysProp() { char prop[PROPERTY_VALUE_MAX]; @@ -3060,23 +3024,6 @@ void SurfaceFlinger::postComposition(PhysicalDisplayId pacesetterId, // Cleanup any outstanding resources due to rendering a prior frame. getRenderEngine().cleanupPostRender(); - { - std::lock_guard lock(mTexturePoolMutex); - if (mTexturePool.size() < mTexturePoolSize) { - const size_t refillCount = mTexturePoolSize - mTexturePool.size(); - const size_t offset = mTexturePool.size(); - mTexturePool.resize(mTexturePoolSize); - getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset); - ATRACE_INT("TexturePoolSize", mTexturePool.size()); - } else if (mTexturePool.size() > mTexturePoolSize) { - const size_t deleteCount = mTexturePool.size() - mTexturePoolSize; - const size_t offset = mTexturePoolSize; - getRenderEngine().deleteTextures(deleteCount, mTexturePool.data() + offset); - mTexturePool.resize(mTexturePoolSize); - ATRACE_INT("TexturePoolSize", mTexturePool.size()); - } - } - if (mNumTrustedPresentationListeners > 0) { // We avoid any reverse traversal upwards so this shouldn't be too expensive traverseLegacyLayers([&](Layer* layer) { @@ -5553,7 +5500,6 @@ status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurface status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp* handle, sp* outLayer) { - args.textureName = getNewTexture(); *outLayer = getFactory().createBufferStateLayer(args); *handle = (*outLayer)->getHandle(); return NO_ERROR; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5d2115c2fb..8ff11e2d1b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -277,13 +277,6 @@ public: // The CompositionEngine encapsulates all composition related interfaces and actions. compositionengine::CompositionEngine& getCompositionEngine() const; - // Obtains a name from the texture pool, or, if the pool is empty, posts a - // synchronous message to the main thread to obtain one on the fly - uint32_t getNewTexture(); - - // utility function to delete a texture on the main thread - void deleteTextureAsync(uint32_t texture); - renderengine::RenderEngine& getRenderEngine() const; void onLayerFirstRef(Layer*); @@ -1274,13 +1267,6 @@ private: TransactionCallbackInvoker mTransactionCallbackInvoker; - // We maintain a pool of pre-generated texture names to hand out to avoid - // layer creation needing to run on the main thread (which it would - // otherwise need to do to access RenderEngine). - std::mutex mTexturePoolMutex; - uint32_t mTexturePoolSize = 0; - std::vector mTexturePool; - std::atomic mNumLayers = 0; // to linkToDeath diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp index b2d4131b5d..ed8bb7fc93 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp @@ -144,9 +144,6 @@ void SurfaceFlingerFuzzer::invokeFlinger() { mFlinger->scheduleRepaint(); mFlinger->scheduleSample(); - uint32_t texture = mFlinger->getNewTexture(); - mFlinger->deleteTextureAsync(texture); - sp handle = defaultServiceManager()->checkService( String16(mFdp.ConsumeRandomLengthString().c_str())); LayerHandle::getLayer(handle); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 14f71f28a2..bdbf243dd4 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -597,7 +597,6 @@ struct BaseLayerProperties { const renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); - EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName); EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha); EXPECT_EQ(false, layer.source.buffer.isOpaque); EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x); @@ -873,15 +872,11 @@ struct BufferLayerVariant : public BaseLayerVariant { using FlingerLayerType = sp; static FlingerLayerType createLayer(CompositionTest* test) { - test->mFlinger.mutableTexturePool().push_back(DEFAULT_TEXTURE_ID); - - FlingerLayerType layer = - Base::template createLayerWithFactory(test, [test]() { - LayerCreationArgs args(test->mFlinger.flinger(), sp(), "test-layer", - LayerProperties::LAYER_FLAGS, LayerMetadata()); - args.textureName = test->mFlinger.mutableTexturePool().back(); - return sp::make(args); - }); + FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { + LayerCreationArgs args(test->mFlinger.flinger(), sp(), "test-layer", + LayerProperties::LAYER_FLAGS, LayerMetadata()); + return sp::make(args); + }); LayerProperties::setupLayerState(test, layer); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index e59d44d745..02fa4153ed 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -631,7 +631,6 @@ public: auto& mutableVisibleRegionsDirty() { return mFlinger->mVisibleRegionsDirty; } auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } - auto& mutableTexturePool() { return mFlinger->mTexturePool; } auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; } auto& mutableMaxRenderTargetSize() { return mFlinger->mMaxRenderTargetSize; } -- cgit v1.2.3-59-g8ed1b From ce6e0044cfea1e0ee38a48714364940a9de3e49a Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Tue, 27 Jun 2023 11:22:54 -0700 Subject: Add setFrameRateCategory surface API Bug: 284911776 Test: atest CtsSurfaceControlTestsStaging Test: atest libsurfaceflinger_unittest Change-Id: Ia804a63198ff096d1e5ffedf6046a0350963b8ed --- libs/gui/LayerState.cpp | 8 + libs/gui/SurfaceComposerClient.cpp | 12 ++ libs/gui/include/gui/LayerState.h | 6 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 + libs/nativewindow/include/system/window.h | 36 ++++ .../FrontEnd/LayerSnapshotBuilder.cpp | 24 ++- .../FrontEnd/RequestedLayerState.cpp | 13 +- services/surfaceflinger/Layer.cpp | 100 +++++------ services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 58 ++++--- services/surfaceflinger/Scheduler/LayerInfo.cpp | 98 ++++++++++- services/surfaceflinger/Scheduler/LayerInfo.h | 60 +++++-- .../Scheduler/RefreshRateSelector.cpp | 102 +++++++++--- .../surfaceflinger/Scheduler/RefreshRateSelector.h | 23 ++- .../Scheduler/include/scheduler/Fps.h | 12 ++ services/surfaceflinger/SurfaceFlinger.cpp | 12 +- .../tests/unittests/LayerHierarchyTest.h | 11 ++ .../tests/unittests/LayerHistoryTest.cpp | 111 +++++++++++++ .../tests/unittests/LayerInfoTest.cpp | 78 +++++++++ .../tests/unittests/LayerSnapshotTest.cpp | 184 ++++++++++++++++----- .../tests/unittests/RefreshRateSelectorTest.cpp | 115 +++++++++++++ .../tests/unittests/SetFrameRateTest.cpp | 56 +++---- 22 files changed, 905 insertions(+), 219 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2322b70d1c..e1afb524e7 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -83,6 +83,7 @@ layer_state_t::layer_state_t() frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS), defaultFrameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), + frameRateCategory(ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT), fixedTransformHint(ui::Transform::ROT_INVALID), autoRefresh(false), isTrustedOverlay(false), @@ -158,6 +159,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeByte, frameRateCompatibility); SAFE_PARCEL(output.writeByte, changeFrameRateStrategy); SAFE_PARCEL(output.writeByte, defaultFrameRateCompatibility); + SAFE_PARCEL(output.writeByte, frameRateCategory); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeBool, autoRefresh); SAFE_PARCEL(output.writeBool, dimmingEnabled); @@ -290,6 +292,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readByte, &frameRateCompatibility); SAFE_PARCEL(input.readByte, &changeFrameRateStrategy); SAFE_PARCEL(input.readByte, &defaultFrameRateCompatibility); + SAFE_PARCEL(input.readByte, &frameRateCategory); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readBool, &autoRefresh); @@ -659,6 +662,10 @@ void layer_state_t::merge(const layer_state_t& other) { frameRateCompatibility = other.frameRateCompatibility; changeFrameRateStrategy = other.changeFrameRateStrategy; } + if (other.what & eFrameRateCategoryChanged) { + what |= eFrameRateCategoryChanged; + frameRateCategory = other.frameRateCategory; + } if (other.what & eFixedTransformHintChanged) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; @@ -769,6 +776,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eFrameRateSelectionPriority, other, frameRateSelectionPriority); CHECK_DIFF3(diff, eFrameRateChanged, other, frameRate, frameRateCompatibility, changeFrameRateStrategy); + CHECK_DIFF(diff, eFrameRateCategoryChanged, other, frameRateCategory); CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint); CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh); CHECK_DIFF(diff, eTrustedOverlayChanged, other, isTrustedOverlay); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 78401205ff..dc35c1c60e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2092,6 +2092,18 @@ SurfaceComposerClient::Transaction::setDefaultFrameRateCompatibility(const sp& sc, int8_t category) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameRateCategoryChanged; + s->frameRateCategory = category; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixedTransformHint( const sp& sc, int32_t fixedTransformHint) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 7aa7068538..03d52d27b5 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -181,7 +181,7 @@ struct layer_state_t { eRelativeLayerChanged = 0x00004000, eReparent = 0x00008000, eColorChanged = 0x00010000, - /* unused = 0x00020000, */ + eFrameRateCategoryChanged = 0x00020000, eBufferTransformChanged = 0x00040000, eTransformToDisplayInverseChanged = 0x00080000, eCropChanged = 0x00100000, @@ -213,7 +213,6 @@ struct layer_state_t { eTrustedOverlayChanged = 0x4000'00000000, eDropInputModeChanged = 0x8000'00000000, eExtendedRangeBrightnessChanged = 0x10000'00000000, - }; layer_state_t(); @@ -358,6 +357,9 @@ struct layer_state_t { // Default frame rate compatibility used to set the layer refresh rate votetype. int8_t defaultFrameRateCompatibility; + // Frame rate category to suggest what frame rate range a surface should run. + int8_t frameRateCategory; + // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that // the graphic producers should receive a transform hint as if the diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index dbcbd3bd62..fd9f186663 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -675,6 +675,8 @@ public: Transaction& setDefaultFrameRateCompatibility(const sp& sc, int8_t compatibility); + Transaction& setFrameRateCategory(const sp& sc, int8_t category); + // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that // the graphic producers should receive a transform hint as if the diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index edaa422e55..e158f01e8c 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1060,6 +1060,42 @@ enum { ANATIVEWINDOW_FRAME_RATE_MIN }; +/* + * Frame rate category values that can be used in Transaction::setFrameRateCategory. + */ +enum { + /** + * Default value. This value can also be set to return to default behavior, such as layers + * without animations. + */ + ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT = 0, + + /** + * The layer will explicitly not influence the frame rate. + * This may indicate a frame rate suitable for no animation updates (such as a cursor blinking + * or a sporadic update). + */ + ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE = 1, + + /** + * Indicates a frame rate suitable for animations that looks fine even if played at a low frame + * rate. + */ + ANATIVEWINDOW_FRAME_RATE_CATEGORY_LOW = 2, + + /** + * Indicates a middle frame rate suitable for animations that do not require higher frame + * rates, or do not benefit from high smoothness. This is normally 60 Hz or close to it. + */ + ANATIVEWINDOW_FRAME_RATE_CATEGORY_NORMAL = 3, + + /** + * Indicates a frame rate suitable for animations that require a high frame rate, which may + * increase smoothness but may also increase power usage. + */ + ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH = 4 +}; + static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy) { return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 159d0f028d..758c46853d 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -675,8 +675,7 @@ void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(LayerSnapshot& snaps } using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility; - if (snapshot.frameRate.rate.isValid() || - snapshot.frameRate.type == FrameRateCompatibility::NoVote) { + if (snapshot.frameRate.isValid()) { // we already have a valid framerate. return; } @@ -684,15 +683,17 @@ void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(LayerSnapshot& snaps // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes // for the same reason we are allowing touch boost for those layers. See // RefreshRateSelector::rankFrameRates for details. - const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() && - childSnapshot.frameRate.type == FrameRateCompatibility::Default; + const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.vote.rate.isValid() && + childSnapshot.frameRate.vote.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = - childSnapshot.frameRate.type == FrameRateCompatibility::NoVote; - const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() && - childSnapshot.frameRate.type == FrameRateCompatibility::Exact; + childSnapshot.frameRate.vote.type == FrameRateCompatibility::NoVote; + const auto layerVotedWithCategory = + childSnapshot.frameRate.category != FrameRateCategory::Default; + const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.vote.rate.isValid() && + childSnapshot.frameRate.vote.type == FrameRateCompatibility::Exact; bool childHasValidFrameRate = layerVotedWithDefaultCompatibility || layerVotedWithNoVote || - layerVotedWithExactCompatibility; + layerVotedWithCategory || layerVotedWithExactCompatibility; // If we don't have a valid frame rate, but the children do, we set this // layer as NoVote to allow the children to control the refresh rate @@ -820,11 +821,8 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a RequestedLayerState::Changes::Hierarchy) || snapshot.changes.any(RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::Hierarchy)) { - snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() || - (requested.requestedFrameRate.type == - scheduler::LayerInfo::FrameRateCompatibility::NoVote)) - ? requested.requestedFrameRate - : parentSnapshot.frameRate; + snapshot.frameRate = requested.requestedFrameRate.isValid() ? requested.requestedFrameRate + : parentSnapshot.frameRate; snapshot.changes |= RequestedLayerState::Changes::FrameRate; } diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index d979c4662e..43800e279f 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include "Layer.h" #include "LayerCreationArgs.h" #include "LayerLog.h" @@ -123,6 +125,7 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) dimmingEnabled = true; defaultFrameRateCompatibility = static_cast(scheduler::LayerInfo::FrameRateCompatibility::Default); + frameRateCategory = static_cast(FrameRateCategory::Default); dataspace = ui::Dataspace::V0_SRGB; gameMode = gui::GameMode::Unsupported; requestedFrameRate = {}; @@ -319,8 +322,14 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta Layer::FrameRate::convertCompatibility(clientState.frameRateCompatibility); const auto strategy = Layer::FrameRate::convertChangeFrameRateStrategy( clientState.changeFrameRateStrategy); - requestedFrameRate = - Layer::FrameRate(Fps::fromValue(clientState.frameRate), compatibility, strategy); + requestedFrameRate.vote = + Layer::FrameRate::FrameRateVote(Fps::fromValue(clientState.frameRate), + compatibility, strategy); + changes |= RequestedLayerState::Changes::FrameRate; + } + if (clientState.what & layer_state_t::eFrameRateCategoryChanged) { + const auto category = Layer::FrameRate::convertCategory(clientState.frameRateCategory); + requestedFrameRate.category = category; changes |= RequestedLayerState::Changes::FrameRate; } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 59a8825de5..95e1a2f0d3 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -101,7 +100,7 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility; using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness; const auto frameRateCompatibility = [frameRate] { - switch (frameRate.type) { + switch (frameRate.vote.type) { case Layer::FrameRateCompatibility::Default: return FrameRateCompatibility::Default; case Layer::FrameRateCompatibility::ExactOrMultiple: @@ -112,7 +111,7 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate }(); const auto seamlessness = [frameRate] { - switch (frameRate.seamlessness) { + switch (frameRate.vote.seamlessness) { case scheduler::Seamlessness::OnlySeamless: return Seamlessness::ShouldBeSeamless; case scheduler::Seamlessness::SeamedAndSeamless: @@ -122,7 +121,7 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate } }(); - return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(), + return TimeStats::SetFrameRateVote{.frameRate = frameRate.vote.rate.getValue(), .frameRateCompatibility = frameRateCompatibility, .seamlessness = seamlessness}; } @@ -1264,8 +1263,7 @@ const half4& Layer::getBorderColor() { bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded) { // The frame rate for layer tree is this layer's frame rate if present, or the parent frame rate const auto frameRate = [&] { - if (mDrawingState.frameRate.rate.isValid() || - mDrawingState.frameRate.type == FrameRateCompatibility::NoVote) { + if (mDrawingState.frameRate.isValid()) { return mDrawingState.frameRate; } @@ -1281,23 +1279,23 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran child->propagateFrameRateForLayerTree(frameRate, transactionNeeded); } - // If we don't have a valid frame rate, but the children do, we set this + // If we don't have a valid frame rate specification, but the children do, we set this // layer as NoVote to allow the children to control the refresh rate - if (!frameRate.rate.isValid() && frameRate.type != FrameRateCompatibility::NoVote && - childrenHaveFrameRate) { + if (!frameRate.isValid() && childrenHaveFrameRate) { *transactionNeeded |= setFrameRateForLayerTreeLegacy(FrameRate(Fps(), FrameRateCompatibility::NoVote)); } - // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for + // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes for // the same reason we are allowing touch boost for those layers. See // RefreshRateSelector::rankFrameRates for details. const auto layerVotedWithDefaultCompatibility = - frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default; - const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote; + frameRate.vote.rate.isValid() && frameRate.vote.type == FrameRateCompatibility::Default; + const auto layerVotedWithNoVote = frameRate.vote.type == FrameRateCompatibility::NoVote; + const auto layerVotedWithCategory = frameRate.category != FrameRateCategory::Default; const auto layerVotedWithExactCompatibility = - frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Exact; - return layerVotedWithDefaultCompatibility || layerVotedWithNoVote || + frameRate.vote.rate.isValid() && frameRate.vote.type == FrameRateCompatibility::Exact; + return layerVotedWithDefaultCompatibility || layerVotedWithNoVote || layerVotedWithCategory || layerVotedWithExactCompatibility || childrenHaveFrameRate; } @@ -1319,13 +1317,28 @@ void Layer::updateTreeHasFrameRateVote() { } } -bool Layer::setFrameRate(FrameRate frameRate) { - if (mDrawingState.frameRate == frameRate) { +bool Layer::setFrameRate(FrameRate::FrameRateVote frameRateVote) { + if (mDrawingState.frameRate.vote == frameRateVote) { return false; } mDrawingState.sequence++; - mDrawingState.frameRate = frameRate; + mDrawingState.frameRate.vote = frameRateVote; + mDrawingState.modified = true; + + updateTreeHasFrameRateVote(); + + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool Layer::setFrameRateCategory(FrameRateCategory category) { + if (mDrawingState.frameRate.category == category) { + return false; + } + + mDrawingState.sequence++; + mDrawingState.frameRate.category = category; mDrawingState.modified = true; updateTreeHasFrameRateVote(); @@ -1651,10 +1664,10 @@ void Layer::miniDumpLegacy(std::string& result, const DisplayDevice& display) co StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); const auto frameRate = getFrameRateForLayerTree(); - if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(), - ftl::enum_string(frameRate.type).c_str(), - ftl::enum_string(frameRate.seamlessness).c_str()); + if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) { + StringAppendF(&result, "%s %15s %17s", to_string(frameRate.vote.rate).c_str(), + ftl::enum_string(frameRate.vote.type).c_str(), + ftl::enum_string(frameRate.vote.seamlessness).c_str()); } else { result.append(41, ' '); } @@ -1686,10 +1699,10 @@ void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapsho StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); const auto frameRate = snapshot.frameRate; - if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(), - ftl::enum_string(frameRate.type).c_str(), - ftl::enum_string(frameRate.seamlessness).c_str()); + if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) { + StringAppendF(&result, "%s %15s %17s", to_string(frameRate.vote.rate).c_str(), + ftl::enum_string(frameRate.vote.type).c_str(), + ftl::enum_string(frameRate.vote.seamlessness).c_str()); } else { result.append(41, ' '); } @@ -2823,36 +2836,6 @@ void Layer::addChildToDrawing(const sp& layer) { layer->mDrawingParent = sp::fromExisting(this); } -Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t compatibility) { - switch (compatibility) { - case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT: - return FrameRateCompatibility::Default; - case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: - return FrameRateCompatibility::ExactOrMultiple; - case ANATIVEWINDOW_FRAME_RATE_EXACT: - return FrameRateCompatibility::Exact; - case ANATIVEWINDOW_FRAME_RATE_MIN: - return FrameRateCompatibility::Min; - case ANATIVEWINDOW_FRAME_RATE_NO_VOTE: - return FrameRateCompatibility::NoVote; - default: - LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); - return FrameRateCompatibility::Default; - } -} - -scheduler::Seamlessness Layer::FrameRate::convertChangeFrameRateStrategy(int8_t strategy) { - switch (strategy) { - case ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS: - return Seamlessness::OnlySeamless; - case ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS: - return Seamlessness::SeamedAndSeamless; - default: - LOG_ALWAYS_FATAL("Invalid change frame sate strategy value %d", strategy); - return Seamlessness::Default; - } -} - bool Layer::isInternalDisplayOverlay() const { const State& s(mDrawingState); if (s.flags & layer_state_t::eLayerSkipScreenshot) { @@ -4366,13 +4349,6 @@ void Layer::updateLastLatchTime(nsecs_t latchTime) { mLastLatchTime = latchTime; } -// --------------------------------------------------------------------------- - -std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) { - return stream << "{rate=" << rate.rate << " type=" << ftl::enum_string(rate.type) - << " seamlessness=" << ftl::enum_string(rate.seamlessness) << '}'; -} - } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d1912e4c9c..568e4c49dd 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -778,7 +778,8 @@ public: */ Rect getCroppedBufferSize(const Layer::State& s) const; - bool setFrameRate(FrameRate); + bool setFrameRate(FrameRate::FrameRateVote); + bool setFrameRateCategory(FrameRateCategory); virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 5d00a26031..565a490ec8 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -40,8 +40,9 @@ namespace android::scheduler { namespace { bool isLayerActive(const LayerInfo& info, nsecs_t threshold) { - // Layers with an explicit vote are always kept active - if (info.getSetFrameRateVote().rate.isValid()) { + // Layers with an explicit frame rate or frame rate category are always kept active, + // but ignore NoVote/NoPreference. + if (info.getSetFrameRateVote().isValid() && !info.getSetFrameRateVote().isNoVote()) { return true; } @@ -70,6 +71,7 @@ void trace(const LayerInfo& info, LayerHistory::LayerVoteType type, int fps) { traceType(LayerHistory::LayerVoteType::ExplicitExact, fps); traceType(LayerHistory::LayerVoteType::Min, 1); traceType(LayerHistory::LayerVoteType::Max, 1); + traceType(LayerHistory::LayerVoteType::ExplicitCategory, 1); ALOGD("%s: %s @ %d Hz", __FUNCTION__, info.getName().c_str(), fps); } @@ -171,27 +173,32 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - layerFocused ? "" : "not"); ATRACE_FORMAT("%s", info->getName().c_str()); - const auto vote = info->getRefreshRateVote(selector, now); - // Skip NoVote layer as those don't have any requirements - if (vote.type == LayerVoteType::NoVote) { - continue; - } + const auto votes = info->getRefreshRateVote(selector, now); + for (LayerInfo::LayerVote vote : votes) { + if (vote.isNoVote()) { + continue; + } + + // Compute the layer's position on the screen + const Rect bounds = Rect(info->getBounds()); + const ui::Transform transform = info->getTransform(); + constexpr bool roundOutwards = true; + Rect transformed = transform.transform(bounds, roundOutwards); + + const float layerArea = transformed.getWidth() * transformed.getHeight(); + float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f; + const std::string categoryString = vote.category == FrameRateCategory::Default + ? base::StringPrintf("category=%s", ftl::enum_string(vote.category).c_str()) + : ""; + ATRACE_FORMAT_INSTANT("%s %s %s (%d%)", ftl::enum_string(vote.type).c_str(), + to_string(vote.fps).c_str(), categoryString.c_str(), + weight * 100); + summary.push_back({info->getName(), info->getOwnerUid(), vote.type, vote.fps, + vote.seamlessness, vote.category, weight, layerFocused}); - // Compute the layer's position on the screen - const Rect bounds = Rect(info->getBounds()); - const ui::Transform transform = info->getTransform(); - constexpr bool roundOutwards = true; - Rect transformed = transform.transform(bounds, roundOutwards); - - const float layerArea = transformed.getWidth() * transformed.getHeight(); - float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f; - ATRACE_FORMAT_INSTANT("%s %s (%d%)", ftl::enum_string(vote.type).c_str(), - to_string(vote.fps).c_str(), weight * 100); - summary.push_back({info->getName(), info->getOwnerUid(), vote.type, vote.fps, - vote.seamlessness, weight, layerFocused}); - - if (CC_UNLIKELY(mTraceEnabled)) { - trace(*info, vote.type, vote.fps.getIntValue()); + if (CC_UNLIKELY(mTraceEnabled)) { + trace(*info, vote.type, vote.fps.getIntValue()); + } } } @@ -228,7 +235,7 @@ void LayerHistory::partitionLayers(nsecs_t now) { // Set layer vote if set const auto frameRate = info->getSetFrameRateVote(); const auto voteType = [&]() { - switch (frameRate.type) { + switch (frameRate.vote.type) { case Layer::FrameRateCompatibility::Default: return LayerVoteType::ExplicitDefault; case Layer::FrameRateCompatibility::Min: @@ -242,9 +249,10 @@ void LayerHistory::partitionLayers(nsecs_t now) { } }(); - if (frameRate.rate.isValid() || voteType == LayerVoteType::NoVote) { + if (frameRate.isValid()) { const auto type = info->isVisible() ? voteType : LayerVoteType::NoVote; - info->setLayerVote({type, frameRate.rate, frameRate.seamlessness}); + info->setLayerVote({type, frameRate.vote.rate, frameRate.vote.seamlessness, + frameRate.category}); } else { info->resetLayerVote(); } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index bae3739501..750803b2f9 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -26,10 +26,12 @@ #include #include +#include #include #include #include #include +#include #undef LOG_TAG #define LOG_TAG "LayerInfo" @@ -265,19 +267,34 @@ std::optional LayerInfo::calculateRefreshRateIfPossible(const RefreshRateSe : std::nullopt; } -LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateSelector& selector, - nsecs_t now) { +LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelector& selector, + nsecs_t now) { ATRACE_CALL(); + LayerInfo::RefreshRateVotes votes; + if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { - ALOGV("%s voted %d ", mName.c_str(), static_cast(mLayerVote.type)); - return mLayerVote; + if (mLayerVote.category != FrameRateCategory::Default) { + ALOGV("%s uses frame rate category: %d", mName.c_str(), + static_cast(mLayerVote.category)); + votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, mLayerVote.fps, + Seamlessness::Default, mLayerVote.category}); + } + + if (mLayerVote.fps.isValid() || + mLayerVote.type != LayerHistory::LayerVoteType::ExplicitDefault) { + ALOGV("%s voted %d ", mName.c_str(), static_cast(mLayerVote.type)); + votes.push_back(mLayerVote); + } + + return votes; } if (isAnimating(now)) { ATRACE_FORMAT_INSTANT("animating"); ALOGV("%s is animating", mName.c_str()); mLastRefreshRate.animating = true; - return {LayerHistory::LayerVoteType::Max, Fps()}; + votes.push_back({LayerHistory::LayerVoteType::Max, Fps()}); + return votes; } const LayerInfo::Frequent frequent = isFrequent(now); @@ -288,7 +305,8 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateSelector& se mLastRefreshRate.infrequent = true; // Infrequent layers vote for minimal refresh rate for // battery saving purposes and also to prevent b/135718869. - return {LayerHistory::LayerVoteType::Min, Fps()}; + votes.push_back({LayerHistory::LayerVoteType::Min, Fps()}); + return votes; } if (frequent.clearHistory) { @@ -298,11 +316,13 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateSelector& se auto refreshRate = calculateRefreshRateIfPossible(selector, now); if (refreshRate.has_value()) { ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str()); - return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; + votes.push_back({LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}); + return votes; } ALOGV("%s Max (can't resolve refresh rate)", mName.c_str()); - return {LayerHistory::LayerVoteType::Max, Fps()}; + votes.push_back({LayerHistory::LayerVoteType::Max, Fps()}); + return votes; } const char* LayerInfo::getTraceTag(LayerHistory::LayerVoteType type) const { @@ -391,6 +411,68 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const { return consistent; } +LayerInfo::FrameRateCompatibility LayerInfo::FrameRate::convertCompatibility(int8_t compatibility) { + switch (compatibility) { + case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT: + return FrameRateCompatibility::Default; + case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: + return FrameRateCompatibility::ExactOrMultiple; + case ANATIVEWINDOW_FRAME_RATE_EXACT: + return FrameRateCompatibility::Exact; + case ANATIVEWINDOW_FRAME_RATE_MIN: + return FrameRateCompatibility::Min; + case ANATIVEWINDOW_FRAME_RATE_NO_VOTE: + return FrameRateCompatibility::NoVote; + default: + LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); + return FrameRateCompatibility::Default; + } +} + +Seamlessness LayerInfo::FrameRate::convertChangeFrameRateStrategy(int8_t strategy) { + switch (strategy) { + case ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS: + return Seamlessness::OnlySeamless; + case ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS: + return Seamlessness::SeamedAndSeamless; + default: + LOG_ALWAYS_FATAL("Invalid change frame sate strategy value %d", strategy); + return Seamlessness::Default; + } +} + +FrameRateCategory LayerInfo::FrameRate::convertCategory(int8_t category) { + switch (category) { + case ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT: + return FrameRateCategory::Default; + case ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE: + return FrameRateCategory::NoPreference; + case ANATIVEWINDOW_FRAME_RATE_CATEGORY_LOW: + return FrameRateCategory::Low; + case ANATIVEWINDOW_FRAME_RATE_CATEGORY_NORMAL: + return FrameRateCategory::Normal; + case ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH: + return FrameRateCategory::High; + default: + LOG_ALWAYS_FATAL("Invalid frame rate category value %d", category); + return FrameRateCategory::Default; + } +} + +bool LayerInfo::FrameRate::isNoVote() const { + return vote.type == FrameRateCompatibility::NoVote || + category == FrameRateCategory::NoPreference; +} + +bool LayerInfo::FrameRate::isValid() const { + return isNoVote() || vote.rate.isValid() || category != FrameRateCategory::Default; +} + +std::ostream& operator<<(std::ostream& stream, const LayerInfo::FrameRate& rate) { + return stream << "{rate=" << rate.vote.rate << " type=" << ftl::enum_string(rate.vote.type) + << " seamlessness=" << ftl::enum_string(rate.vote.seamlessness) << '}'; +} + } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index c5a60573f5..7d2444c94b 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -25,6 +25,7 @@ #include #include +#include #include #include "LayerHistory.h" @@ -67,8 +68,15 @@ public: LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic; Fps fps; Seamlessness seamlessness = Seamlessness::Default; + // Category is in effect if fps is not specified. + FrameRateCategory category = FrameRateCategory::Default; + + // Returns true if the layer explicitly should contribute to frame rate scoring. + bool isNoVote() const { return RefreshRateSelector::isNoVote(type, category); } }; + using RefreshRateVotes = ftl::SmallVector; + // FrameRateCompatibility specifies how we should interpret the frame rate associated with // the layer. enum class FrameRateCompatibility { @@ -87,24 +95,40 @@ public: ftl_last = NoVote }; - // Encapsulates the frame rate and compatibility of the layer. This information will be used + // Encapsulates the frame rate specifications of the layer. This information will be used // when the display refresh rate is determined. struct FrameRate { using Seamlessness = scheduler::Seamlessness; - Fps rate; - FrameRateCompatibility type = FrameRateCompatibility::Default; - Seamlessness seamlessness = Seamlessness::Default; + // Information related to a specific desired frame rate vote. + struct FrameRateVote { + Fps rate; + FrameRateCompatibility type = FrameRateCompatibility::Default; + Seamlessness seamlessness = Seamlessness::Default; + + bool operator==(const FrameRateVote& other) const { + return isApproxEqual(rate, other.rate) && type == other.type && + seamlessness == other.seamlessness; + } + + FrameRateVote() = default; + + FrameRateVote(Fps rate, FrameRateCompatibility type, + Seamlessness seamlessness = Seamlessness::OnlySeamless) + : rate(rate), type(type), seamlessness(getSeamlessness(rate, seamlessness)) {} + } vote; + + FrameRateCategory category = FrameRateCategory::Default; FrameRate() = default; FrameRate(Fps rate, FrameRateCompatibility type, - Seamlessness seamlessness = Seamlessness::OnlySeamless) - : rate(rate), type(type), seamlessness(getSeamlessness(rate, seamlessness)) {} + Seamlessness seamlessness = Seamlessness::OnlySeamless, + FrameRateCategory category = FrameRateCategory::Default) + : vote(FrameRateVote(rate, type, seamlessness)), category(category) {} bool operator==(const FrameRate& other) const { - return isApproxEqual(rate, other.rate) && type == other.type && - seamlessness == other.seamlessness; + return vote == other.vote && category == other.category; } bool operator!=(const FrameRate& other) const { return !(*this == other); } @@ -112,8 +136,22 @@ public: // Convert an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value to a // Layer::FrameRateCompatibility. Logs fatal if the compatibility value is invalid. static FrameRateCompatibility convertCompatibility(int8_t compatibility); + + // Convert an ANATIVEWINDOW_CHANGE_FRAME_RATE_* value to a scheduler::Seamlessness. + // Logs fatal if the compatibility value is invalid. static scheduler::Seamlessness convertChangeFrameRateStrategy(int8_t strategy); + // Convert an ANATIVEWINDOW_FRAME_RATE_CATEGORY_* value to a FrameRateCategory. + // Logs fatal if the compatibility value is invalid. + static FrameRateCategory convertCategory(int8_t category); + + // True if the FrameRate has explicit frame rate specifications. + bool isValid() const; + + // Returns true if the FrameRate explicitly instructs to not contribute to frame rate + // selection. + bool isNoVote() const; + private: static Seamlessness getSeamlessness(Fps rate, Seamlessness seamlessness) { if (!rate.isValid()) { @@ -148,13 +186,15 @@ public: void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; } // Resets the layer vote to its default. - void resetLayerVote() { mLayerVote = {mDefaultVote, Fps(), Seamlessness::Default}; } + void resetLayerVote() { + mLayerVote = {mDefaultVote, Fps(), Seamlessness::Default, FrameRateCategory::Default}; + } std::string getName() const { return mName; } uid_t getOwnerUid() const { return mOwnerUid; } - LayerVote getRefreshRateVote(const RefreshRateSelector&, nsecs_t now); + RefreshRateVotes getRefreshRateVote(const RefreshRateSelector&, nsecs_t now); // Return the last updated time. If the present time is farther in the future than the // updated time, the updated time is the present time. diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index fb985f7c5b..a7ba731323 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -275,6 +275,25 @@ std::pair RefreshRateSelector::getDisplayFrames(nsecs_t layerP return {quotient, remainder}; } +float RefreshRateSelector::calculateNonExactMatchingDefaultLayerScoreLocked( + nsecs_t displayPeriod, nsecs_t layerPeriod) const { + // Find the actual rate the layer will render, assuming + // that layerPeriod is the minimal period to render a frame. + // For example if layerPeriod is 20ms and displayPeriod is 16ms, + // then the actualLayerPeriod will be 32ms, because it is the + // smallest multiple of the display period which is >= layerPeriod. + auto actualLayerPeriod = displayPeriod; + int multiplier = 1; + while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) { + multiplier++; + actualLayerPeriod = displayPeriod * multiplier; + } + + // Because of the threshold we used above it's possible that score is slightly + // above 1. + return std::min(1.0f, static_cast(layerPeriod) / static_cast(actualLayerPeriod)); +} + float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate) const { constexpr float kScoreForFractionalPairs = .8f; @@ -282,22 +301,7 @@ float RefreshRateSelector::calculateNonExactMatchingLayerScoreLocked(const Layer const auto displayPeriod = refreshRate.getPeriodNsecs(); const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs(); if (layer.vote == LayerVoteType::ExplicitDefault) { - // Find the actual rate the layer will render, assuming - // that layerPeriod is the minimal period to render a frame. - // For example if layerPeriod is 20ms and displayPeriod is 16ms, - // then the actualLayerPeriod will be 32ms, because it is the - // smallest multiple of the display period which is >= layerPeriod. - auto actualLayerPeriod = displayPeriod; - int multiplier = 1; - while (layerPeriod > actualLayerPeriod + MARGIN_FOR_PERIOD_CALCULATION) { - multiplier++; - actualLayerPeriod = displayPeriod * multiplier; - } - - // Because of the threshold we used above it's possible that score is slightly - // above 1. - return std::min(1.0f, - static_cast(layerPeriod) / static_cast(actualLayerPeriod)); + return calculateNonExactMatchingDefaultLayerScoreLocked(displayPeriod, layerPeriod); } if (layer.vote == LayerVoteType::ExplicitExactOrMultiple || @@ -372,6 +376,22 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay constexpr float kSeamedSwitchPenalty = 0.95f; const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; + if (layer.vote == LayerVoteType::ExplicitCategory) { + if (getFrameRateCategoryRange(layer.frameRateCategory).includes(refreshRate)) { + return 1.f; + } + + FpsRange categoryRange = getFrameRateCategoryRange(layer.frameRateCategory); + using fps_approx_ops::operator<; + if (refreshRate < categoryRange.min) { + return calculateNonExactMatchingDefaultLayerScoreLocked(refreshRate.getPeriodNsecs(), + categoryRange.min + .getPeriodNsecs()); + } + return calculateNonExactMatchingDefaultLayerScoreLocked(refreshRate.getPeriodNsecs(), + categoryRange.max.getPeriodNsecs()); + } + // If the layer wants Max, give higher score to the higher refresh rate if (layer.vote == LayerVoteType::Max) { return calculateDistanceScoreFromMax(refreshRate); @@ -391,7 +411,8 @@ float RefreshRateSelector::calculateLayerScoreLocked(const LayerRequirement& lay // If the layer frame rate is a divisor of the refresh rate it should score // the highest score. - if (getFrameRateDivisor(refreshRate, layer.desiredRefreshRate) > 0) { + if (layer.desiredRefreshRate.isValid() && + getFrameRateDivisor(refreshRate, layer.desiredRefreshRate) > 0) { return 1.0f * seamlessness; } @@ -441,6 +462,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector 0 || - explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0; + explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0 || + explicitCategoryVoteLayers > 0; const Policy* policy = getCurrentPolicyLocked(); const auto& defaultMode = mDisplayModes.get(policy->defaultMode)->get(); @@ -536,10 +562,11 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vectorvote != LayerVoteType::ExplicitDefault && - layer->vote != LayerVoteType::ExplicitExactOrMultiple && - layer->vote != LayerVoteType::ExplicitExact); + layer->vote != LayerVoteType::ExplicitExactOrMultiple && + layer->vote != LayerVoteType::ExplicitExact && + layer->vote != LayerVoteType::ExplicitCategory, + "Invalid layer vote type for frame rate overrides"); for (auto& [fps, score] : scoredFrameRates) { constexpr bool isSeamlessSwitch = true; const auto layerScore = calculateLayerScoreLocked(*layer, fps, isSeamlessSwitch); @@ -1380,6 +1411,27 @@ std::chrono::milliseconds RefreshRateSelector::getIdleTimerTimeout() { return mConfig.idleTimerTimeout; } +// TODO(b/293651105): Extract category FpsRange mapping to OEM-configurable config. +FpsRange RefreshRateSelector::getFrameRateCategoryRange(FrameRateCategory category) { + switch (category) { + case FrameRateCategory::High: + return FpsRange{90_Hz, 120_Hz}; + case FrameRateCategory::Normal: + return FpsRange{60_Hz, 90_Hz}; + case FrameRateCategory::Low: + return FpsRange{30_Hz, 60_Hz}; + case FrameRateCategory::NoPreference: + case FrameRateCategory::Default: + LOG_ALWAYS_FATAL("Should not get fps range for frame rate category: %s", + ftl::enum_string(category).c_str()); + return FpsRange{0_Hz, 0_Hz}; + default: + LOG_ALWAYS_FATAL("Invalid frame rate category for range: %s", + ftl::enum_string(category).c_str()); + return FpsRange{0_Hz, 0_Hz}; + } +} + } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 7af8d0397f..41db38d705 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -147,8 +147,9 @@ public: // ExactOrMultiple compatibility ExplicitExact, // Specific refresh rate that was provided by the app with // Exact compatibility + ExplicitCategory, // Specific frame rate category was provided by the app - ftl_last = ExplicitExact + ftl_last = ExplicitCategory }; // Captures the layer requirements for a refresh rate. This will be used to determine the @@ -164,6 +165,8 @@ public: Fps desiredRefreshRate; // If a seamless mode switch is required. Seamlessness seamlessness = Seamlessness::Default; + // Layer frame rate category. Superseded by desiredRefreshRate. + FrameRateCategory frameRateCategory = FrameRateCategory::Default; // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer // would have on choosing the refresh rate. float weight = 0.0f; @@ -174,12 +177,20 @@ public: return name == other.name && vote == other.vote && isApproxEqual(desiredRefreshRate, other.desiredRefreshRate) && seamlessness == other.seamlessness && weight == other.weight && - focused == other.focused; + focused == other.focused && frameRateCategory == other.frameRateCategory; } bool operator!=(const LayerRequirement& other) const { return !(*this == other); } + + bool isNoVote() const { return RefreshRateSelector::isNoVote(vote, frameRateCategory); } }; + // Returns true if the layer explicitly instructs to not contribute to refresh rate selection. + // In other words, true if the layer should be ignored. + static bool isNoVote(LayerVoteType vote, FrameRateCategory category) { + return vote == LayerVoteType::NoVote || category == FrameRateCategory::NoPreference; + } + // Global state describing signals that affect refresh rate choice. struct GlobalSignals { // Whether the user touched the screen recently. Used to apply touch boost. @@ -344,6 +355,9 @@ public: Fps displayFrameRate, GlobalSignals) const EXCLUDES(mLock); + // Gets the FpsRange that the FrameRateCategory represents. + static FpsRange getFrameRateCategoryRange(FrameRateCategory category); + std::optional kernelIdleTimerController() { return mConfig.kernelIdleTimerController; } @@ -447,6 +461,11 @@ private: float calculateNonExactMatchingLayerScoreLocked(const LayerRequirement&, Fps refreshRate) const REQUIRES(mLock); + // Calculates the score for non-exact matching layer that has LayerVoteType::ExplicitDefault. + float calculateNonExactMatchingDefaultLayerScoreLocked(nsecs_t displayPeriod, + nsecs_t layerPeriod) const + REQUIRES(mLock); + void updateDisplayModes(DisplayModes, DisplayModeId activeModeId) EXCLUDES(mLock) REQUIRES(kMainThreadContext); diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h index d6329e246c..19e951abb2 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace android { @@ -81,6 +82,17 @@ struct FpsRanges { bool valid() const; }; +// The frame rate category of a Layer. +enum class FrameRateCategory { + Default, + NoPreference, + Low, + Normal, + High, + + ftl_last = High +}; + static_assert(std::is_trivially_copyable_v); constexpr Fps operator""_Hz(unsigned long long frequency) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 06adfec0d2..5c25dbce0c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5192,9 +5192,15 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime const auto strategy = Layer::FrameRate::convertChangeFrameRateStrategy(s.changeFrameRateStrategy); - if (layer->setFrameRate( - Layer::FrameRate(Fps::fromValue(s.frameRate), compatibility, strategy))) { - flags |= eTraversalNeeded; + if (layer->setFrameRate(Layer::FrameRate::FrameRateVote(Fps::fromValue(s.frameRate), + compatibility, strategy))) { + flags |= eTraversalNeeded; + } + } + if (what & layer_state_t::eFrameRateCategoryChanged) { + const FrameRateCategory category = Layer::FrameRate::convertCategory(s.frameRateCategory); + if (layer->setFrameRateCategory(category)) { + flags |= eTraversalNeeded; } } if (what & layer_state_t::eFixedTransformHintChanged) { diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h index f64ba2a439..93438d8666 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h @@ -335,6 +335,17 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) { + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = layer_state_t::eFrameRateCategoryChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.frameRateCategory = frameRateCategory; + mLifecycleManager.applyTransactions(transactions); + } + void setRoundedCorners(uint32_t id, float radius) { std::vector transactions; transactions.emplace_back(); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 85d86a7acc..51b5b05bed 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -437,6 +437,117 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { EXPECT_EQ(0, frequentLayerCount(time)); } +TEST_F(LayerHistoryTest, oneLayerExplicitCategory) { + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()) + .WillRepeatedly( + Return(Layer::FrameRate(0_Hz, Layer::FrameRateCompatibility::Default, + Seamlessness::OnlySeamless, FrameRateCategory::High))); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = systemTime(); + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer->getSequence(), layer->getLayerProps(), time, time, + LayerHistory::LayerUpdateType::Buffer); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, summarizeLayerHistory(time).size()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + // First LayerRequirement is the frame rate specification + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); + + // layer became inactive, but the vote stays + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(1, summarizeLayerHistory(time).size()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); +} + +// This test case should be the same as oneLayerNoVote except instead of layer vote is NoVote, +// the category is NoPreference. +TEST_F(LayerHistoryTest, oneLayerCategoryNoPreference) { + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()) + .WillRepeatedly(Return(Layer::FrameRate(0_Hz, Layer::FrameRateCompatibility::Default, + Seamlessness::OnlySeamless, + FrameRateCategory::NoPreference))); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = systemTime(); + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer->getSequence(), layer->getLayerProps(), time, time, + LayerHistory::LayerUpdateType::Buffer); + time += HI_FPS_PERIOD; + } + + ASSERT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory) { + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()) + .WillRepeatedly( + Return(Layer::FrameRate(73.4_Hz, Layer::FrameRateCompatibility::Default, + Seamlessness::OnlySeamless, FrameRateCategory::High))); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = systemTime(); + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer->getSequence(), layer->getLayerProps(), time, time, + LayerHistory::LayerUpdateType::Buffer); + time += HI_FPS_PERIOD; + } + + // There are 2 LayerRequirement's due to the frame rate category. + ASSERT_EQ(2, summarizeLayerHistory(time).size()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + // First LayerRequirement is the layer's category specification + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); + + // Second LayerRequirement is the frame rate specification + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[1].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[1].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[1].frameRateCategory); + + // layer became inactive, but the vote stays + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(2, summarizeLayerHistory(time).size()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); +} + TEST_F(LayerHistoryTest, multipleLayers) { auto layer1 = createLayer("A"); auto layer2 = createLayer("B"); diff --git a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp index 5c2d2e1f43..e0133d6010 100644 --- a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp @@ -24,13 +24,23 @@ #include "FpsOps.h" #include "Scheduler/LayerHistory.h" #include "Scheduler/LayerInfo.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockSchedulerCallback.h" namespace android::scheduler { +using android::mock::createDisplayMode; + class LayerInfoTest : public testing::Test { protected: using FrameTimeData = LayerInfo::FrameTimeData; + static constexpr Fps LO_FPS = 30_Hz; + static constexpr Fps HI_FPS = 90_Hz; + + LayerInfoTest() { mFlinger.resetScheduler(mScheduler); } + void setFrameTimes(const std::deque& frameTimes) { layerInfo.mFrameTimes = frameTimes; } @@ -43,6 +53,16 @@ protected: auto calculateAverageFrameTime() { return layerInfo.calculateAverageFrameTime(); } LayerInfo layerInfo{"TestLayerInfo", 0, LayerHistory::LayerVoteType::Heuristic}; + + std::shared_ptr mSelector = + std::make_shared(makeModes(createDisplayMode(DisplayModeId(0), + LO_FPS), + createDisplayMode(DisplayModeId(1), + HI_FPS)), + DisplayModeId(0)); + mock::SchedulerCallback mSchedulerCallback; + TestableScheduler* mScheduler = new TestableScheduler(mSelector, mSchedulerCallback); + TestableSurfaceFlinger mFlinger; }; namespace { @@ -171,5 +191,63 @@ TEST_F(LayerInfoTest, ignoresLargePeriods) { ASSERT_EQ(kExpectedFps, Fps::fromPeriodNsecs(*averageFrameTime)); } +TEST_F(LayerInfoTest, getRefreshRateVote_explicitVote) { + LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault, + .fps = 20_Hz}; + layerInfo.setLayerVote(vote); + + auto actualVotes = + layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime()); + ASSERT_EQ(actualVotes.size(), 1u); + ASSERT_EQ(actualVotes[0].type, vote.type); + ASSERT_EQ(actualVotes[0].fps, vote.fps); + ASSERT_EQ(actualVotes[0].seamlessness, vote.seamlessness); + ASSERT_EQ(actualVotes[0].category, vote.category); +} + +TEST_F(LayerInfoTest, getRefreshRateVote_explicitVoteWithCategory) { + LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault, + .fps = 20_Hz, + .category = FrameRateCategory::High}; + layerInfo.setLayerVote(vote); + + auto actualVotes = + layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime()); + ASSERT_EQ(actualVotes.size(), 2u); + ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory); + ASSERT_EQ(actualVotes[0].category, vote.category); + ASSERT_EQ(actualVotes[1].type, vote.type); + ASSERT_EQ(actualVotes[1].fps, vote.fps); + ASSERT_EQ(actualVotes[1].seamlessness, vote.seamlessness); + ASSERT_EQ(actualVotes[1].category, vote.category); +} + +TEST_F(LayerInfoTest, getRefreshRateVote_explicitCategory) { + // When a layer only has a category set, the LayerVoteType should be the LayerInfo's default. + // The most common case should be Heuristic. + LayerInfo::LayerVote vote = {.type = LayerHistory::LayerVoteType::ExplicitDefault, + .category = FrameRateCategory::High}; + layerInfo.setLayerVote(vote); + + auto actualVotes = + layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime()); + ASSERT_EQ(actualVotes.size(), 1u); + ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::ExplicitCategory); + ASSERT_EQ(actualVotes[0].category, vote.category); +} + +TEST_F(LayerInfoTest, getRefreshRateVote_noData) { + LayerInfo::LayerVote vote = { + .type = LayerHistory::LayerVoteType::Heuristic, + }; + layerInfo.setLayerVote(vote); + + auto actualVotes = + layerInfo.getRefreshRateVote(*mScheduler->refreshRateSelector(), systemTime()); + ASSERT_EQ(actualVotes.size(), 1u); + ASSERT_EQ(actualVotes[0].type, LayerHistory::LayerVoteType::Max); + ASSERT_EQ(actualVotes[0].fps, vote.fps); +} + } // namespace } // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 84c37759ba..67cd4c67eb 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -314,13 +314,15 @@ TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) { mLifecycleManager.applyTransactions(transactions); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - EXPECT_EQ(getSnapshot(11)->frameRate.rate.getIntValue(), 90); - EXPECT_EQ(getSnapshot(11)->frameRate.type, scheduler::LayerInfo::FrameRateCompatibility::Exact); - EXPECT_EQ(getSnapshot(111)->frameRate.rate.getIntValue(), 90); - EXPECT_EQ(getSnapshot(111)->frameRate.type, + EXPECT_EQ(getSnapshot(11)->frameRate.vote.rate.getIntValue(), 90); + EXPECT_EQ(getSnapshot(11)->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Exact); - EXPECT_EQ(getSnapshot(1)->frameRate.rate.getIntValue(), 0); - EXPECT_EQ(getSnapshot(1)->frameRate.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote); + EXPECT_EQ(getSnapshot(111)->frameRate.vote.rate.getIntValue(), 90); + EXPECT_EQ(getSnapshot(111)->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Exact); + EXPECT_EQ(getSnapshot(1)->frameRate.vote.rate.getIntValue(), 0); + EXPECT_EQ(getSnapshot(1)->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::NoVote); } TEST_F(LayerSnapshotTest, CanCropTouchableRegion) { @@ -525,21 +527,21 @@ TEST_F(LayerSnapshotTest, framerate) { UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); // verify parent is gets no vote - EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 1})->frameRate.type, + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer and children get the requested votes - EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 11})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 11})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); - EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 111})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 111})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); @@ -549,24 +551,24 @@ TEST_F(LayerSnapshotTest, framerate) { std::vector expected = {1, 11, 111, 122, 1221, 12, 121, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); // verify parent is gets no vote - EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 1})->frameRate.type, + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote); // verify layer and children get the requested votes - EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 11})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 11})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); - EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 111})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 111})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); - EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 122})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 122})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); @@ -576,31 +578,31 @@ TEST_F(LayerSnapshotTest, framerate) { UPDATE_AND_VERIFY(mSnapshotBuilder, expected); // verify old parent has invalid framerate (default) - EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 1})->frameRate.type, + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify new parent get no vote - EXPECT_FALSE(getSnapshot({.id = 2})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 2})->frameRate.type, + EXPECT_FALSE(getSnapshot({.id = 2})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 2})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 2})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer and children get the requested votes (unchanged) - EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 11})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 11})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); - EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 111})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 111})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); - EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.rate.isValid()); - EXPECT_EQ(getSnapshot({.id = 122})->frameRate.rate.getValue(), 244.f); - EXPECT_EQ(getSnapshot({.id = 122})->frameRate.type, + EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, scheduler::LayerInfo::FrameRateCompatibility::Default); } @@ -610,6 +612,112 @@ TEST_F(LayerSnapshotTest, translateDataspace) { EXPECT_EQ(getSnapshot({.id = 1})->dataspace, ui::Dataspace::V0_SRGB); } +// This test is similar to "frameRate" test case but checks that the setFrameRateCategory API +// interaction also works correctly with the setFrameRate API within SF frontend. +TEST_F(LayerSnapshotTest, frameRateWithCategory) { + // ROOT + // ├── 1 + // │ ├── 11 (frame rate set to 244.f) + // │ │ └── 111 + // │ ├── 12 + // │ │ ├── 121 + // │ │ └── 122 (frame rate category set to Normal) + // │ │ └── 1221 + // │ └── 13 + // └── 2 + setFrameRate(11, 244.f, 0, 0); + setFrameRateCategory(122, 3 /* Normal */); + + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + // verify parent 1 gets no vote + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::NoVote); + EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify layer 11 and children 111 get the requested votes + EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify parent 12 gets no vote + EXPECT_FALSE(getSnapshot({.id = 12})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 12})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::NoVote); + EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify layer 122 and children 1221 get the requested votes + EXPECT_FALSE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); + EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.isValid()); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.category, FrameRateCategory::Normal); + EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_FALSE(getSnapshot({.id = 1221})->frameRate.vote.rate.isValid()); + EXPECT_TRUE(getSnapshot({.id = 1221})->frameRate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.category, FrameRateCategory::Normal); + EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // reparent and verify the child does NOT get the new parent's framerate because it already has + // the frame rate category specified. + // ROOT + // ├─1 + // │ ├─11 (frame rate set to 244.f) + // │ │ ├─111 + // │ │ └─122 (frame rate category set to Normal) + // │ │ └─1221 + // │ ├─12 + // │ │ └─121 + // │ └─13 + // └─2 + reparentLayer(122, 11); + + std::vector expected = {1, 11, 111, 122, 1221, 12, 121, 13, 2}; + UPDATE_AND_VERIFY(mSnapshotBuilder, expected); + // verify parent is gets no vote + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::NoVote); + + // verify layer 11 and children 111 get the requested votes + EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + + EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + + // verify layer 122 and children 1221 get the requested category vote (unchanged from + // reparenting) + EXPECT_FALSE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); + EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.isValid()); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.category, FrameRateCategory::Normal); + EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_FALSE(getSnapshot({.id = 1221})->frameRate.vote.rate.isValid()); + EXPECT_TRUE(getSnapshot({.id = 1221})->frameRate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::Default); + EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.category, FrameRateCategory::Normal); + EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); +} + TEST_F(LayerSnapshotTest, skipRoundCornersWhenProtected) { setRoundedCorners(1, 42.f); setRoundedCorners(2, 42.f); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index aaf55fbeae..dc6b70032a 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include "DisplayHardware/HWC2.h" #include "FpsOps.h" @@ -1381,6 +1382,120 @@ TEST_P(RefreshRateSelectorTest, touchConsidered) { EXPECT_FALSE(signals.touch); } +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60_90_120) { + auto selector = createSelector(makeModes(kMode30, kMode60, kMode90, kMode120), kModeId60); + + std::vector layers = {{.vote = LayerVoteType::ExplicitDefault, .weight = 1.f}, + {.vote = LayerVoteType::ExplicitCategory, + .weight = 1.f}}; + auto& lr = layers[0]; + + struct Case { + // Params + Fps desiredFrameRate = 0_Hz; + FrameRateCategory frameRateCategory = FrameRateCategory::Default; + + // Expected result + Fps expectedFrameRate = 0_Hz; + }; + + // Prepare a table with the vote and the expected refresh rate + const std::initializer_list testCases = { + // Cases that only have frame rate category requirements, but no desired frame rate. + // When frame rates get an equal score, the lower is chosen, unless there are Max votes. + {0_Hz, FrameRateCategory::High, 90_Hz}, + {0_Hz, FrameRateCategory::Normal, 60_Hz}, + {0_Hz, FrameRateCategory::Low, 30_Hz}, + {0_Hz, FrameRateCategory::NoPreference, 60_Hz}, + + // Cases that have both desired frame rate and frame rate category requirements. + {24_Hz, FrameRateCategory::High, 120_Hz}, + {30_Hz, FrameRateCategory::High, 90_Hz}, + {12_Hz, FrameRateCategory::Normal, 60_Hz}, + {30_Hz, FrameRateCategory::NoPreference, 30_Hz}, + + // Cases that only have desired frame rate. + {30_Hz, FrameRateCategory::Default, 30_Hz}, + }; + + for (auto testCase : testCases) { + ALOGI("**** %s: Testing desiredFrameRate=%s, frameRateCategory=%s", __func__, + to_string(testCase.desiredFrameRate).c_str(), + ftl::enum_string(testCase.frameRateCategory).c_str()); + + lr.desiredRefreshRate = testCase.desiredFrameRate; + + std::stringstream ss; + ss << to_string(testCase.desiredFrameRate) + << ", category=" << ftl::enum_string(testCase.frameRateCategory); + lr.name = ss.str(); + + if (testCase.frameRateCategory != FrameRateCategory::Default) { + layers[1].frameRateCategory = testCase.frameRateCategory; + } + + EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getFps()) + << "did not get expected frame rate for " << lr.name; + } +} + +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_60_120) { + auto selector = createSelector(makeModes(kMode60, kMode120), kModeId60); + + std::vector layers = {{.vote = LayerVoteType::ExplicitDefault, .weight = 1.f}, + {.vote = LayerVoteType::ExplicitCategory, + .weight = 1.f}}; + auto& lr = layers[0]; + + struct Case { + // Params + Fps desiredFrameRate = 0_Hz; + FrameRateCategory frameRateCategory = FrameRateCategory::Default; + + // Expected result + Fps expectedFrameRate = 0_Hz; + }; + + // Prepare a table with the vote and the expected refresh rate + const std::initializer_list testCases = { + // Cases that only have frame rate category requirements, but no desired frame rate. + // When frame rates get an equal score, the lower is chosen, unless there are Max votes. + {0_Hz, FrameRateCategory::High, 120_Hz}, + {0_Hz, FrameRateCategory::Normal, 60_Hz}, + {0_Hz, FrameRateCategory::Low, 60_Hz}, + {0_Hz, FrameRateCategory::NoPreference, 60_Hz}, + + // Cases that have both desired frame rate and frame rate category requirements. + {24_Hz, FrameRateCategory::High, 120_Hz}, + {30_Hz, FrameRateCategory::High, 120_Hz}, + {12_Hz, FrameRateCategory::Normal, 60_Hz}, + {30_Hz, FrameRateCategory::NoPreference, 60_Hz}, + + // Cases that only have desired frame rate. + {30_Hz, FrameRateCategory::Default, 60_Hz}, + }; + + for (auto testCase : testCases) { + ALOGI("**** %s: Testing desiredFrameRate=%s, frameRateCategory=%s", __func__, + to_string(testCase.desiredFrameRate).c_str(), + ftl::enum_string(testCase.frameRateCategory).c_str()); + + lr.desiredRefreshRate = testCase.desiredFrameRate; + + std::stringstream ss; + ss << to_string(testCase.desiredFrameRate) + << ", category=" << ftl::enum_string(testCase.frameRateCategory); + lr.name = ss.str(); + + if (testCase.frameRateCategory != FrameRateCategory::Default) { + layers[1].frameRateCategory = testCase.frameRateCategory; + } + + EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getFps()) + << "did not get expected frame rate for " << lr.name; + } +} + TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitDefault) { auto selector = createSelector(kModes_60_90_72_120, kModeId60); diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index a1e4e25c06..608fa762ef 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -97,7 +97,7 @@ TEST_P(SetFrameRateTest, SetAndGet) { const auto& layerFactory = GetParam(); auto layer = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - layer->setFrameRate(FRAME_RATE_VOTE1); + layer->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE1, layer->getFrameRateForLayerTree()); } @@ -114,13 +114,13 @@ TEST_P(SetFrameRateTest, SetAndGetParent) { addChild(parent, child1); addChild(child1, child2); - child2->setFrameRate(FRAME_RATE_VOTE1); + child2->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - child2->setFrameRate(FRAME_RATE_NO_VOTE); + child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -139,27 +139,27 @@ TEST_P(SetFrameRateTest, SetAndGetParentAllVote) { addChild(parent, child1); addChild(child1, child2); - child2->setFrameRate(FRAME_RATE_VOTE1); - child1->setFrameRate(FRAME_RATE_VOTE2); - parent->setFrameRate(FRAME_RATE_VOTE3); + child2->setFrameRate(FRAME_RATE_VOTE1.vote); + child1->setFrameRate(FRAME_RATE_VOTE2.vote); + parent->setFrameRate(FRAME_RATE_VOTE3.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - child2->setFrameRate(FRAME_RATE_NO_VOTE); + child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE2, child2->getFrameRateForLayerTree()); - child1->setFrameRate(FRAME_RATE_NO_VOTE); + child1->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE3, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE3, child2->getFrameRateForLayerTree()); - parent->setFrameRate(FRAME_RATE_NO_VOTE); + parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -178,13 +178,13 @@ TEST_P(SetFrameRateTest, SetAndGetChild) { addChild(parent, child1); addChild(child1, child2); - parent->setFrameRate(FRAME_RATE_VOTE1); + parent->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - parent->setFrameRate(FRAME_RATE_NO_VOTE); + parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -203,27 +203,27 @@ TEST_P(SetFrameRateTest, SetAndGetChildAllVote) { addChild(parent, child1); addChild(child1, child2); - child2->setFrameRate(FRAME_RATE_VOTE1); - child1->setFrameRate(FRAME_RATE_VOTE2); - parent->setFrameRate(FRAME_RATE_VOTE3); + child2->setFrameRate(FRAME_RATE_VOTE1.vote); + child1->setFrameRate(FRAME_RATE_VOTE2.vote); + parent->setFrameRate(FRAME_RATE_VOTE3.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - parent->setFrameRate(FRAME_RATE_NO_VOTE); + parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - child1->setFrameRate(FRAME_RATE_NO_VOTE); + child1->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - child2->setFrameRate(FRAME_RATE_NO_VOTE); + child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -241,7 +241,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildAddAfterVote) { addChild(parent, child1); - parent->setFrameRate(FRAME_RATE_VOTE1); + parent->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); @@ -253,7 +253,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildAddAfterVote) { EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - parent->setFrameRate(FRAME_RATE_NO_VOTE); + parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -272,7 +272,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildRemoveAfterVote) { addChild(parent, child1); addChild(child1, child2); - parent->setFrameRate(FRAME_RATE_VOTE1); + parent->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); @@ -284,7 +284,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildRemoveAfterVote) { EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - parent->setFrameRate(FRAME_RATE_NO_VOTE); + parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -305,14 +305,14 @@ TEST_P(SetFrameRateTest, SetAndGetParentNotInTree) { addChild(child1, child2); addChild(child1, child2_1); - child2->setFrameRate(FRAME_RATE_VOTE1); + child2->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child2_1->getFrameRateForLayerTree()); - child2->setFrameRate(FRAME_RATE_NO_VOTE); + child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); @@ -375,7 +375,7 @@ TEST_P(SetFrameRateTest, SetOnParentActivatesTree) { auto child = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); addChild(parent, child); - parent->setFrameRate(FRAME_RATE_VOTE1); + parent->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); auto& history = mFlinger.mutableScheduler().mutableLayerHistory(); @@ -388,8 +388,8 @@ TEST_P(SetFrameRateTest, SetOnParentActivatesTree) { const auto summary = history.summarize(*selectorPtr, 0); ASSERT_EQ(2u, summary.size()); - EXPECT_EQ(FRAME_RATE_VOTE1.rate, summary[0].desiredRefreshRate); - EXPECT_EQ(FRAME_RATE_VOTE1.rate, summary[1].desiredRefreshRate); + EXPECT_EQ(FRAME_RATE_VOTE1.vote.rate, summary[0].desiredRefreshRate); + EXPECT_EQ(FRAME_RATE_VOTE1.vote.rate, summary[1].desiredRefreshRate); } TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) { @@ -405,7 +405,7 @@ TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) { addChild(parent, child1); addChild(child1, childOfChild1); - childOfChild1->setFrameRate(FRAME_RATE_VOTE1); + childOfChild1->setFrameRate(FRAME_RATE_VOTE1.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); @@ -419,7 +419,7 @@ TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) { EXPECT_EQ(FRAME_RATE_VOTE1, childOfChild1->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - childOfChild1->setFrameRate(FRAME_RATE_NO_VOTE); + childOfChild1->setFrameRate(FRAME_RATE_NO_VOTE.vote); commitTransaction(); EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); -- cgit v1.2.3-59-g8ed1b From bec51fdc3c8a42cbcb833d7d14800fbb0a14a7f3 Mon Sep 17 00:00:00 2001 From: Kean Mariotti Date: Wed, 19 Apr 2023 13:31:02 +0000 Subject: Move proto definitions to external/perfetto This commit moves the layer and transaction .proto files to external/perfetto/protos/perfetto/trace/android/. Test: atest libsurfaceflinger_unittest && atest transactiontrace_testsuite Bug: b/284424784 Change-Id: I60b4a51fbb092d44759b7085536e1299815597f8 --- services/surfaceflinger/Layer.cpp | 26 +- services/surfaceflinger/Layer.h | 12 +- services/surfaceflinger/LayerProtoHelper.cpp | 83 +++--- services/surfaceflinger/LayerProtoHelper.h | 62 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 29 +- services/surfaceflinger/SurfaceFlinger.h | 10 +- .../Tracing/TransactionProtoParser.cpp | 82 +++--- .../Tracing/TransactionProtoParser.h | 28 +- .../surfaceflinger/Tracing/TransactionTracing.cpp | 39 +-- .../surfaceflinger/Tracing/TransactionTracing.h | 22 +- .../Tracing/tools/LayerTraceGenerator.cpp | 4 +- .../Tracing/tools/LayerTraceGenerator.h | 4 +- services/surfaceflinger/Tracing/tools/main.cpp | 2 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 3 +- services/surfaceflinger/layerproto/Android.bp | 38 +-- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 25 +- services/surfaceflinger/layerproto/common.proto | 92 ------ services/surfaceflinger/layerproto/display.proto | 42 --- .../include/layerproto/LayerProtoHeader.h | 7 +- .../include/layerproto/LayerProtoParser.h | 21 +- .../include/layerproto/TransactionProto.h | 6 +- .../surfaceflinger/layerproto/jarjar-rules.txt | 1 - services/surfaceflinger/layerproto/layers.proto | 171 ------------ .../surfaceflinger/layerproto/layerstrace.proto | 69 ----- .../surfaceflinger/layerproto/transactions.proto | 310 --------------------- services/surfaceflinger/tests/Stress_test.cpp | 8 +- .../tests/tracing/TransactionTraceTestSuite.cpp | 4 +- .../tests/unittests/TransactionProtoParserTest.cpp | 4 +- .../tests/unittests/TransactionTracingTest.cpp | 26 +- 29 files changed, 296 insertions(+), 934 deletions(-) delete mode 100644 services/surfaceflinger/layerproto/common.proto delete mode 100644 services/surfaceflinger/layerproto/display.proto delete mode 100644 services/surfaceflinger/layerproto/jarjar-rules.txt delete mode 100644 services/surfaceflinger/layerproto/layers.proto delete mode 100644 services/surfaceflinger/layerproto/layerstrace.proto delete mode 100644 services/surfaceflinger/layerproto/transactions.proto (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 057fa70bc3..075ea00134 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -140,7 +140,7 @@ using gui::WindowInfo; using PresentState = frametimeline::SurfaceFrame::PresentState; -Layer::Layer(const LayerCreationArgs& args) +Layer::Layer(const surfaceflinger::LayerCreationArgs& args) : sequence(args.sequence), mFlinger(sp::fromExisting(args.flinger)), mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)), @@ -1001,8 +1001,8 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; std::string name = mName + "BackgroundColorLayer"; mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer( - LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, - LayerMetadata())); + surfaceflinger::LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, + LayerMetadata())); // add to child list addChild(mDrawingState.bgColorLayer); @@ -2190,8 +2190,9 @@ void Layer::setInputInfo(const WindowInfo& info) { setTransactionFlags(eTransactionNeeded); } -LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { - LayerProto* layerProto = layersProto.add_layers(); +perfetto::protos::LayerProto* Layer::writeToProto(perfetto::protos::LayersProto& layersProto, + uint32_t traceFlags) { + perfetto::protos::LayerProto* layerProto = layersProto.add_layers(); writeToProtoDrawingState(layerProto); writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); @@ -2208,20 +2209,22 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { return layerProto; } -void Layer::writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack) { +void Layer::writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto, + ui::LayerStack layerStack) { ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread. ftl::FakeGuard mainThreadGuard(kMainThreadContext); // Only populate for the primary display. if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) { const auto compositionType = getCompositionType(*display); - layerProto->set_hwc_composition_type(static_cast(compositionType)); + layerProto->set_hwc_composition_type( + static_cast(compositionType)); LayerProtoHelper::writeToProto(getVisibleRegion(display), [&]() { return layerProto->mutable_visible_region(); }); } } -void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { +void Layer::writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo) { const ui::Transform transform = getTransform(); auto buffer = getExternalTexture(); if (buffer != nullptr) { @@ -2260,8 +2263,8 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { layerInfo->set_shadow_radius(mEffectiveShadowRadius); } -void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, - uint32_t traceFlags) { +void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, + LayerVector::StateSet stateSet, uint32_t traceFlags) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mDrawingState; @@ -3610,7 +3613,8 @@ Rect Layer::computeBufferCrop(const State& s) { } sp Layer::createClone(uint32_t mirrorRootId) { - LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()); + surfaceflinger::LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, + LayerMetadata()); sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->setInitialValuesForClone(sp::fromExisting(this), mirrorRootId); return layer; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8a65d9dba6..3b3647edd4 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -235,7 +235,7 @@ public: bool useVsyncIdForRefreshRateSelection = false; }; - explicit Layer(const LayerCreationArgs& args); + explicit Layer(const surfaceflinger::LayerCreationArgs& args); virtual ~Layer(); static bool isLayerFocusedBasedOnPriority(int32_t priority); @@ -634,17 +634,19 @@ public: bool isRemovedFromCurrentState() const; - LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags); - void writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack); + perfetto::protos::LayerProto* writeToProto(perfetto::protos::LayersProto& layersProto, + uint32_t traceFlags); + void writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto, + ui::LayerStack layerStack); // Write states that are modified by the main thread. This includes drawing // state as well as buffer data. This should be called in the main or tracing // thread. - void writeToProtoDrawingState(LayerProto* layerInfo); + void writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo); // Write drawing or current state. If writing current state, the caller should hold the // external mStateLock. If writing drawing state, this function should be called on the // main or tracing thread. - void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet, + void writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, LayerVector::StateSet, uint32_t traceFlags = LayerTracing::TRACE_ALL); gui::WindowInfo::Type getWindowType() const { return mWindowType; } diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 341f041086..144e1f5abf 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -29,28 +29,30 @@ using gui::WindowInfo; namespace surfaceflinger { -void LayerProtoHelper::writePositionToProto(const float x, const float y, - std::function getPositionProto) { +void LayerProtoHelper::writePositionToProto( + const float x, const float y, + std::function getPositionProto) { if (x != 0 || y != 0) { // Use a lambda do avoid writing the object header when the object is empty - PositionProto* position = getPositionProto(); + perfetto::protos::PositionProto* position = getPositionProto(); position->set_x(x); position->set_y(y); } } -void LayerProtoHelper::writeSizeToProto(const uint32_t w, const uint32_t h, - std::function getSizeProto) { +void LayerProtoHelper::writeSizeToProto( + const uint32_t w, const uint32_t h, + std::function getSizeProto) { if (w != 0 || h != 0) { // Use a lambda do avoid writing the object header when the object is empty - SizeProto* size = getSizeProto(); + perfetto::protos::SizeProto* size = getSizeProto(); size->set_w(w); size->set_h(h); } } -void LayerProtoHelper::writeToProto(const Region& region, - std::function getRegionProto) { +void LayerProtoHelper::writeToProto( + const Region& region, std::function getRegionProto) { if (region.isEmpty()) { return; } @@ -58,7 +60,8 @@ void LayerProtoHelper::writeToProto(const Region& region, writeToProto(region, getRegionProto()); } -void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) { +void LayerProtoHelper::writeToProto(const Region& region, + perfetto::protos::RegionProto* regionProto) { if (region.isEmpty()) { return; } @@ -72,7 +75,8 @@ void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionPro } } -void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& outRegion) { +void LayerProtoHelper::readFromProto(const perfetto::protos::RegionProto& regionProto, + Region& outRegion) { for (int i = 0; i < regionProto.rect_size(); i++) { Rect rect; readFromProto(regionProto.rect(i), rect); @@ -80,32 +84,34 @@ void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& out } } -void LayerProtoHelper::writeToProto(const Rect& rect, std::function getRectProto) { +void LayerProtoHelper::writeToProto(const Rect& rect, + std::function getRectProto) { if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) { // Use a lambda do avoid writing the object header when the object is empty writeToProto(rect, getRectProto()); } } -void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { +void LayerProtoHelper::writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto) { rectProto->set_left(rect.left); rectProto->set_top(rect.top); rectProto->set_bottom(rect.bottom); rectProto->set_right(rect.right); } -void LayerProtoHelper::readFromProto(const RectProto& proto, Rect& outRect) { +void LayerProtoHelper::readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect) { outRect.left = proto.left(); outRect.top = proto.top(); outRect.bottom = proto.bottom(); outRect.right = proto.right(); } -void LayerProtoHelper::writeToProto(const FloatRect& rect, - std::function getFloatRectProto) { +void LayerProtoHelper::writeToProto( + const FloatRect& rect, + std::function getFloatRectProto) { if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) { // Use a lambda do avoid writing the object header when the object is empty - FloatRectProto* rectProto = getFloatRectProto(); + perfetto::protos::FloatRectProto* rectProto = getFloatRectProto(); rectProto->set_left(rect.left); rectProto->set_top(rect.top); rectProto->set_bottom(rect.bottom); @@ -113,10 +119,11 @@ void LayerProtoHelper::writeToProto(const FloatRect& rect, } } -void LayerProtoHelper::writeToProto(const half4 color, std::function getColorProto) { +void LayerProtoHelper::writeToProto(const half4 color, + std::function getColorProto) { if (color.r != 0 || color.g != 0 || color.b != 0 || color.a != 0) { // Use a lambda do avoid writing the object header when the object is empty - ColorProto* colorProto = getColorProto(); + perfetto::protos::ColorProto* colorProto = getColorProto(); colorProto->set_r(color.r); colorProto->set_g(color.g); colorProto->set_b(color.b); @@ -125,7 +132,7 @@ void LayerProtoHelper::writeToProto(const half4 color, std::functionset_type(type); @@ -141,7 +148,7 @@ void LayerProtoHelper::writeToProtoDeprecated(const ui::Transform& transform, } void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform, - TransformProto* transformProto) { + perfetto::protos::TransformProto* transformProto) { const uint32_t type = transform.getType() | (transform.getOrientation() << 8); transformProto->set_type(type); @@ -156,12 +163,13 @@ void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform, } } -void LayerProtoHelper::writeToProto(const renderengine::ExternalTexture& buffer, - std::function getActiveBufferProto) { +void LayerProtoHelper::writeToProto( + const renderengine::ExternalTexture& buffer, + std::function getActiveBufferProto) { if (buffer.getWidth() != 0 || buffer.getHeight() != 0 || buffer.getUsage() != 0 || buffer.getPixelFormat() != 0) { // Use a lambda do avoid writing the object header when the object is empty - ActiveBufferProto* activeBufferProto = getActiveBufferProto(); + auto* activeBufferProto = getActiveBufferProto(); activeBufferProto->set_width(buffer.getWidth()); activeBufferProto->set_height(buffer.getHeight()); activeBufferProto->set_stride(buffer.getUsage()); @@ -171,12 +179,12 @@ void LayerProtoHelper::writeToProto(const renderengine::ExternalTexture& buffer, void LayerProtoHelper::writeToProto( const WindowInfo& inputInfo, const wp& touchableRegionBounds, - std::function getInputWindowInfoProto) { + std::function getInputWindowInfoProto) { if (inputInfo.token == nullptr) { return; } - InputWindowInfoProto* proto = getInputWindowInfoProto(); + perfetto::protos::InputWindowInfoProto* proto = getInputWindowInfoProto(); proto->set_layout_params_flags(inputInfo.layoutParamsFlags.get()); proto->set_input_config(inputInfo.inputConfig.get()); using U = std::underlying_type_t; @@ -209,7 +217,8 @@ void LayerProtoHelper::writeToProto( } } -void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto) { +void LayerProtoHelper::writeToProto(const mat4 matrix, + perfetto::protos::ColorTransformProto* colorTransformProto) { for (int i = 0; i < mat4::ROW_SIZE; i++) { for (int j = 0; j < mat4::COL_SIZE; j++) { colorTransformProto->add_val(matrix[i][j]); @@ -217,7 +226,8 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colo } } -void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix) { +void LayerProtoHelper::readFromProto( + const perfetto::protos::ColorTransformProto& colorTransformProto, mat4& matrix) { for (int i = 0; i < mat4::ROW_SIZE; i++) { for (int j = 0; j < mat4::COL_SIZE; j++) { matrix[i][j] = colorTransformProto.val(i * mat4::COL_SIZE + j); @@ -225,7 +235,8 @@ void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformPr } } -void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion* proto) { +void LayerProtoHelper::writeToProto(const android::BlurRegion region, + perfetto::protos::BlurRegion* proto) { proto->set_blur_radius(region.blurRadius); proto->set_corner_radius_tl(region.cornerRadiusTL); proto->set_corner_radius_tr(region.cornerRadiusTR); @@ -238,7 +249,8 @@ void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion proto->set_bottom(region.bottom); } -void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion) { +void LayerProtoHelper::readFromProto(const perfetto::protos::BlurRegion& proto, + android::BlurRegion& outRegion) { outRegion.blurRadius = proto.blur_radius(); outRegion.cornerRadiusTL = proto.corner_radius_tl(); outRegion.cornerRadiusTR = proto.corner_radius_tr(); @@ -251,7 +263,8 @@ void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegio outRegion.bottom = proto.bottom(); } -LayersProto LayerProtoFromSnapshotGenerator::generate(const frontend::LayerHierarchy& root) { +perfetto::protos::LayersProto LayerProtoFromSnapshotGenerator::generate( + const frontend::LayerHierarchy& root) { mLayersProto.clear_layers(); std::unordered_set stackIdsToSkip; if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) { @@ -310,7 +323,7 @@ frontend::LayerSnapshot* LayerProtoFromSnapshotGenerator::getSnapshot( void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( const frontend::LayerHierarchy& root, frontend::LayerHierarchy::TraversalPath& path) { using Variant = frontend::LayerHierarchy::Variant; - LayerProto* layerProto = mLayersProto.add_layers(); + perfetto::protos::LayerProto* layerProto = mLayersProto.add_layers(); const frontend::RequestedLayerState& layer = *root.getLayer(); frontend::LayerSnapshot* snapshot = getSnapshot(path, layer); LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags); @@ -349,7 +362,7 @@ void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( } } -void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, +void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerInfo, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags) { @@ -446,9 +459,9 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, [&]() { return layerInfo->mutable_destination_frame(); }); } -google::protobuf::RepeatedPtrField LayerProtoHelper::writeDisplayInfoToProto( - const frontend::DisplayInfos& displayInfos) { - google::protobuf::RepeatedPtrField displays; +google::protobuf::RepeatedPtrField +LayerProtoHelper::writeDisplayInfoToProto(const frontend::DisplayInfos& displayInfos) { + google::protobuf::RepeatedPtrField displays; displays.Reserve(displayInfos.size()); for (const auto& [layerStack, displayInfo] : displayInfos) { auto displayProto = displays.Add(); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 346685f259..20c226006c 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -35,39 +35,47 @@ namespace android { namespace surfaceflinger { class LayerProtoHelper { public: - static void writePositionToProto(const float x, const float y, - std::function getPositionProto); + static void writePositionToProto( + const float x, const float y, + std::function getPositionProto); static void writeSizeToProto(const uint32_t w, const uint32_t h, - std::function getSizeProto); - static void writeToProto(const Rect& rect, std::function getRectProto); - static void writeToProto(const Rect& rect, RectProto* rectProto); - static void readFromProto(const RectProto& proto, Rect& outRect); + std::function getSizeProto); + static void writeToProto(const Rect& rect, + std::function getRectProto); + static void writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto); + static void readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect); static void writeToProto(const FloatRect& rect, - std::function getFloatRectProto); - static void writeToProto(const Region& region, std::function getRegionProto); - static void writeToProto(const Region& region, RegionProto* regionProto); - static void readFromProto(const RegionProto& regionProto, Region& outRegion); - static void writeToProto(const half4 color, std::function getColorProto); + std::function getFloatRectProto); + static void writeToProto(const Region& region, + std::function getRegionProto); + static void writeToProto(const Region& region, perfetto::protos::RegionProto* regionProto); + static void readFromProto(const perfetto::protos::RegionProto& regionProto, Region& outRegion); + static void writeToProto(const half4 color, + std::function getColorProto); // This writeToProto for transform is incorrect, but due to backwards compatibility, we can't // update Layers to use it. Use writeTransformToProto for any new transform proto data. static void writeToProtoDeprecated(const ui::Transform& transform, - TransformProto* transformProto); + perfetto::protos::TransformProto* transformProto); static void writeTransformToProto(const ui::Transform& transform, - TransformProto* transformProto); - static void writeToProto(const renderengine::ExternalTexture& buffer, - std::function getActiveBufferProto); - static void writeToProto(const gui::WindowInfo& inputInfo, - const wp& touchableRegionBounds, - std::function getInputWindowInfoProto); - static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto); - static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix); - static void writeToProto(const android::BlurRegion region, BlurRegion*); - static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion); - static void writeSnapshotToProto(LayerProto* outProto, + perfetto::protos::TransformProto* transformProto); + static void writeToProto( + const renderengine::ExternalTexture& buffer, + std::function getActiveBufferProto); + static void writeToProto( + const gui::WindowInfo& inputInfo, const wp& touchableRegionBounds, + std::function getInputWindowInfoProto); + static void writeToProto(const mat4 matrix, + perfetto::protos::ColorTransformProto* colorTransformProto); + static void readFromProto(const perfetto::protos::ColorTransformProto& colorTransformProto, + mat4& matrix); + static void writeToProto(const android::BlurRegion region, perfetto::protos::BlurRegion*); + static void readFromProto(const perfetto::protos::BlurRegion& proto, + android::BlurRegion& outRegion); + static void writeSnapshotToProto(perfetto::protos::LayerProto* outProto, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags); - static google::protobuf::RepeatedPtrField writeDisplayInfoToProto( - const frontend::DisplayInfos&); + static google::protobuf::RepeatedPtrField + writeDisplayInfoToProto(const frontend::DisplayInfos&); }; class LayerProtoFromSnapshotGenerator { @@ -80,7 +88,7 @@ public: mLegacyLayers(legacyLayers), mDisplayInfos(displayInfos), mTraceFlags(traceFlags) {} - LayersProto generate(const frontend::LayerHierarchy& root); + perfetto::protos::LayersProto generate(const frontend::LayerHierarchy& root); private: void writeHierarchyToProto(const frontend::LayerHierarchy& root, @@ -92,7 +100,7 @@ private: const std::unordered_map>& mLegacyLayers; const frontend::DisplayInfos& mDisplayInfos; uint32_t mTraceFlags; - LayersProto mLayersProto; + perfetto::protos::LayersProto mLayersProto; // winscope expects all the layers, so provide a snapshot even if it not currently drawing std::unordered_map diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d978cf64a5..f61b4ded25 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5859,9 +5859,10 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { } if (dumpLayers) { - LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto(); - LayersTraceProto* layersTrace = traceFileProto.add_entry(); - LayersProto layersProto = dumpProtoFromMainThread(); + perfetto::protos::LayersTraceFileProto traceFileProto = + mLayerTracing.createTraceFileProto(); + perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); + perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread(); layersTrace->mutable_layers()->Swap(&layersProto); auto displayProtos = dumpDisplayProto(); layersTrace->mutable_displays()->Swap(&displayProtos); @@ -6087,7 +6088,7 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } -LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { +perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { std::unordered_set stackIdsToSkip; // Determine if virtual layers display should be skipped @@ -6100,7 +6101,7 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } if (mLegacyFrontEndEnabled) { - LayersProto layersProto; + perfetto::protos::LayersProto layersProto; for (const sp& layer : mDrawingState.layersSortedByZ) { if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { continue; @@ -6115,10 +6116,11 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { .generate(mLayerHierarchyBuilder.getHierarchy()); } -google::protobuf::RepeatedPtrField SurfaceFlinger::dumpDisplayProto() const { - google::protobuf::RepeatedPtrField displays; +google::protobuf::RepeatedPtrField +SurfaceFlinger::dumpDisplayProto() const { + google::protobuf::RepeatedPtrField displays; for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { - DisplayProto* displayProto = displays.Add(); + perfetto::protos::DisplayProto* displayProto = displays.Add(); displayProto->set_id(display->getId().value); displayProto->set_name(display->getDisplayName()); displayProto->set_layer_stack(display->getLayerStack().id); @@ -6145,10 +6147,11 @@ void SurfaceFlinger::dumpHwc(std::string& result) const { getHwComposer().dump(result); } -void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const { +void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, + uint32_t traceFlags) const { // Add a fake invisible root layer to the proto output and parent all the offscreen layers to // it. - LayerProto* rootProto = layersProto.add_layers(); + perfetto::protos::LayerProto* rootProto = layersProto.add_layers(); const int32_t offscreenRootLayerId = INT32_MAX - 2; rootProto->set_id(offscreenRootLayerId); rootProto->set_name("Offscreen Root"); @@ -6159,12 +6162,12 @@ void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t rootProto->add_children(offscreenLayer->sequence); // Add layer - LayerProto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); + auto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); layerProto->set_parent(offscreenRootLayerId); } } -LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { +perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { return mScheduler->schedule([=] { return dumpDrawingStateProto(traceFlags); }).get(); } @@ -8747,7 +8750,7 @@ frontend::Update SurfaceFlinger::flushLifecycleUpdates() { void SurfaceFlinger::addToLayerTracing(bool visibleRegionDirty, TimePoint time, VsyncId vsyncId) { const uint32_t tracingFlags = mLayerTracing.getFlags(); - LayersProto layers(dumpDrawingStateProto(tracingFlags)); + perfetto::protos::LayersProto layers(dumpDrawingStateProto(tracingFlags)); if (tracingFlags & LayerTracing::TRACE_EXTRA) { dumpOffscreenLayersProto(layers); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7b64489028..21b7fafc68 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1088,17 +1088,17 @@ private: void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); - LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; - void dumpOffscreenLayersProto(LayersProto& layersProto, + perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; + void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, uint32_t traceFlags = LayerTracing::TRACE_ALL) const; - google::protobuf::RepeatedPtrField dumpDisplayProto() const; + google::protobuf::RepeatedPtrField dumpDisplayProto() const; void addToLayerTracing(bool visibleRegionDirty, TimePoint, VsyncId) REQUIRES(kMainThreadContext); // Dumps state from HW Composer void dumpHwc(std::string& result) const; - LayersProto dumpProtoFromMainThread(uint32_t traceFlags = LayerTracing::TRACE_ALL) - EXCLUDES(mStateLock); + perfetto::protos::LayersProto dumpProtoFromMainThread( + uint32_t traceFlags = LayerTracing::TRACE_ALL) EXCLUDES(mStateLock); void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock); void dumpPlannerInfo(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index b1e3d6378a..2dc89b55ba 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -51,8 +51,8 @@ public: ~FakeExternalTexture() = default; }; -proto::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { - proto::TransactionState proto; +perfetto::protos::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { + perfetto::protos::TransactionState proto; proto.set_pid(t.originPid); proto.set_uid(t.originUid); proto.set_vsync_id(t.frameTimelineInfo.vsyncId); @@ -79,21 +79,21 @@ proto::TransactionState TransactionProtoParser::toProto(const TransactionState& return proto; } -proto::TransactionState TransactionProtoParser::toProto( +perfetto::protos::TransactionState TransactionProtoParser::toProto( const std::map& states) { - proto::TransactionState proto; + perfetto::protos::TransactionState proto; proto.mutable_layer_changes()->Reserve(static_cast(states.size())); for (auto& [layerId, state] : states) { - proto::LayerState layerProto = toProto(state); + perfetto::protos::LayerState layerProto = toProto(state); layerProto.set_has_sideband_stream(state.hasSidebandStream); proto.mutable_layer_changes()->Add(std::move(layerProto)); } return proto; } -proto::LayerState TransactionProtoParser::toProto( +perfetto::protos::LayerState TransactionProtoParser::toProto( const ResolvedComposerState& resolvedComposerState) { - proto::LayerState proto; + perfetto::protos::LayerState proto; auto& layer = resolvedComposerState.state; proto.set_layer_id(resolvedComposerState.layerId); proto.set_what(layer.what); @@ -114,7 +114,7 @@ proto::LayerState TransactionProtoParser::toProto( proto.set_mask(layer.mask); } if (layer.what & layer_state_t::eMatrixChanged) { - proto::LayerState_Matrix22* matrixProto = proto.mutable_matrix(); + perfetto::protos::LayerState_Matrix22* matrixProto = proto.mutable_matrix(); matrixProto->set_dsdx(layer.matrix.dsdx); matrixProto->set_dsdy(layer.matrix.dsdy); matrixProto->set_dtdx(layer.matrix.dtdx); @@ -132,7 +132,7 @@ proto::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eColorChanged) { - proto::LayerState_Color3* colorProto = proto.mutable_color(); + perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color(); colorProto->set_r(layer.color.r); colorProto->set_g(layer.color.g); colorProto->set_b(layer.color.b); @@ -150,13 +150,14 @@ proto::LayerState TransactionProtoParser::toProto( LayerProtoHelper::writeToProto(layer.crop, proto.mutable_crop()); } if (layer.what & layer_state_t::eBufferChanged) { - proto::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); + perfetto::protos::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); if (resolvedComposerState.externalTexture) { bufferProto->set_buffer_id(resolvedComposerState.externalTexture->getId()); bufferProto->set_width(resolvedComposerState.externalTexture->getWidth()); bufferProto->set_height(resolvedComposerState.externalTexture->getHeight()); - bufferProto->set_pixel_format(static_cast( - resolvedComposerState.externalTexture->getPixelFormat())); + bufferProto->set_pixel_format( + static_cast( + resolvedComposerState.externalTexture->getPixelFormat())); bufferProto->set_usage(resolvedComposerState.externalTexture->getUsage()); } bufferProto->set_frame_number(layer.bufferData->frameNumber); @@ -191,7 +192,8 @@ proto::LayerState TransactionProtoParser::toProto( if (layer.what & layer_state_t::eInputInfoChanged) { if (layer.windowInfoHandle) { const gui::WindowInfo* inputInfo = layer.windowInfoHandle->getInfo(); - proto::LayerState_WindowInfo* windowInfoProto = proto.mutable_window_info_handle(); + perfetto::protos::LayerState_WindowInfo* windowInfoProto = + proto.mutable_window_info_handle(); windowInfoProto->set_layout_params_flags(inputInfo->layoutParamsFlags.get()); windowInfoProto->set_layout_params_type( static_cast(inputInfo->layoutParamsType)); @@ -204,7 +206,7 @@ proto::LayerState TransactionProtoParser::toProto( windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test( gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)); windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor); - proto::Transform* transformProto = windowInfoProto->mutable_transform(); + perfetto::protos::Transform* transformProto = windowInfoProto->mutable_transform(); transformProto->set_dsdx(inputInfo->transform.dsdx()); transformProto->set_dtdx(inputInfo->transform.dtdx()); transformProto->set_dtdy(inputInfo->transform.dtdy()); @@ -219,7 +221,7 @@ proto::LayerState TransactionProtoParser::toProto( if (layer.what & layer_state_t::eBackgroundColorChanged) { proto.set_bg_color_alpha(layer.bgColor.a); proto.set_bg_color_dataspace(static_cast(layer.bgColorDataspace)); - proto::LayerState_Color3* colorProto = proto.mutable_color(); + perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color(); colorProto->set_r(layer.bgColor.r); colorProto->set_g(layer.bgColor.g); colorProto->set_b(layer.bgColor.b); @@ -255,13 +257,13 @@ proto::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eDropInputModeChanged) { proto.set_drop_input_mode( - static_cast(layer.dropInputMode)); + static_cast(layer.dropInputMode)); } return proto; } -proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) { - proto::DisplayState proto; +perfetto::protos::DisplayState TransactionProtoParser::toProto(const DisplayState& display) { + perfetto::protos::DisplayState proto; proto.set_what(display.what); proto.set_id(mMapper->getDisplayId(display.token)); @@ -285,8 +287,8 @@ proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) return proto; } -proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) { - proto::LayerCreationArgs proto; +perfetto::protos::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) { + perfetto::protos::LayerCreationArgs proto; proto.set_layer_id(args.sequence); proto.set_name(args.name); proto.set_flags(args.flags); @@ -297,7 +299,8 @@ proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs return proto; } -TransactionState TransactionProtoParser::fromProto(const proto::TransactionState& proto) { +TransactionState TransactionProtoParser::fromProto( + const perfetto::protos::TransactionState& proto) { TransactionState t; t.originPid = proto.pid(); t.originUid = proto.uid(); @@ -323,7 +326,7 @@ TransactionState TransactionProtoParser::fromProto(const proto::TransactionState return t; } -void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto, +void TransactionProtoParser::fromProto(const perfetto::protos::LayerCreationArgs& proto, LayerCreationArgs& outArgs) { outArgs.sequence = proto.layer_id(); @@ -335,7 +338,7 @@ void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto, outArgs.layerStackToMirror.id = proto.layer_stack_to_mirror(); } -void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto, +void TransactionProtoParser::mergeFromProto(const perfetto::protos::LayerState& proto, TracingLayerState& outState) { ResolvedComposerState resolvedComposerState; fromProto(proto, resolvedComposerState); @@ -360,7 +363,7 @@ void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto, } } -void TransactionProtoParser::fromProto(const proto::LayerState& proto, +void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto, ResolvedComposerState& resolvedComposerState) { auto& layer = resolvedComposerState.state; resolvedComposerState.layerId = proto.layer_id(); @@ -381,7 +384,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer.mask = proto.mask(); } if (proto.what() & layer_state_t::eMatrixChanged) { - const proto::LayerState_Matrix22& matrixProto = proto.matrix(); + const perfetto::protos::LayerState_Matrix22& matrixProto = proto.matrix(); layer.matrix.dsdx = matrixProto.dsdx(); layer.matrix.dsdy = matrixProto.dsdy(); layer.matrix.dtdx = matrixProto.dtdx(); @@ -399,7 +402,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, } if (proto.what() & layer_state_t::eColorChanged) { - const proto::LayerState_Color3& colorProto = proto.color(); + const perfetto::protos::LayerState_Color3& colorProto = proto.color(); layer.color.r = colorProto.r(); layer.color.g = colorProto.g(); layer.color.b = colorProto.b(); @@ -417,7 +420,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, LayerProtoHelper::readFromProto(proto.crop(), layer.crop); } if (proto.what() & layer_state_t::eBufferChanged) { - const proto::LayerState_BufferData& bufferProto = proto.buffer_data(); + const perfetto::protos::LayerState_BufferData& bufferProto = proto.buffer_data(); layer.bufferData = std::make_shared(bufferProto.buffer_id(), bufferProto.width(), bufferProto.height(), bufferProto.pixel_format(), @@ -460,7 +463,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, if ((proto.what() & layer_state_t::eInputInfoChanged) && proto.has_window_info_handle()) { gui::WindowInfo inputInfo; - const proto::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle(); + const perfetto::protos::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle(); inputInfo.layoutParamsFlags = static_cast(windowInfoProto.layout_params_flags()); @@ -472,7 +475,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, ftl::Flags(windowInfoProto.input_config()); inputInfo.surfaceInset = windowInfoProto.surface_inset(); inputInfo.globalScaleFactor = windowInfoProto.global_scale_factor(); - const proto::Transform& transformProto = windowInfoProto.transform(); + const perfetto::protos::Transform& transformProto = windowInfoProto.transform(); inputInfo.transform.set(transformProto.dsdx(), transformProto.dtdx(), transformProto.dtdy(), transformProto.dsdy()); inputInfo.transform.set(transformProto.tx(), transformProto.ty()); @@ -485,7 +488,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, if (proto.what() & layer_state_t::eBackgroundColorChanged) { layer.bgColor.a = proto.bg_color_alpha(); layer.bgColorDataspace = static_cast(proto.bg_color_dataspace()); - const proto::LayerState_Color3& colorProto = proto.color(); + const perfetto::protos::LayerState_Color3& colorProto = proto.color(); layer.bgColor.r = colorProto.r(); layer.bgColor.g = colorProto.g(); layer.bgColor.b = colorProto.b(); @@ -525,7 +528,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, } } -DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) { +DisplayState TransactionProtoParser::fromProto(const perfetto::protos::DisplayState& proto) { DisplayState display; display.what = proto.what(); display.token = mMapper->getDisplayHandle(proto.id()); @@ -550,7 +553,7 @@ DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) return display; } -void asProto(proto::Transform* proto, const ui::Transform& transform) { +void asProto(perfetto::protos::Transform* proto, const ui::Transform& transform) { proto->set_dsdx(transform.dsdx()); proto->set_dtdx(transform.dtdx()); proto->set_dtdy(transform.dtdy()); @@ -559,9 +562,9 @@ void asProto(proto::Transform* proto, const ui::Transform& transform) { proto->set_ty(transform.ty()); } -proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& displayInfo, - uint32_t layerStack) { - proto::DisplayInfo proto; +perfetto::protos::DisplayInfo TransactionProtoParser::toProto( + const frontend::DisplayInfo& displayInfo, uint32_t layerStack) { + perfetto::protos::DisplayInfo proto; proto.set_layer_stack(layerStack); proto.set_display_id(displayInfo.info.displayId); proto.set_logical_width(displayInfo.info.logicalWidth); @@ -577,12 +580,13 @@ proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& return proto; } -void fromProto2(ui::Transform& outTransform, const proto::Transform& proto) { +void fromProto2(ui::Transform& outTransform, const perfetto::protos::Transform& proto) { outTransform.set(proto.dsdx(), proto.dtdx(), proto.dtdy(), proto.dsdy()); outTransform.set(proto.tx(), proto.ty()); } -frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo& proto) { +frontend::DisplayInfo TransactionProtoParser::fromProto( + const perfetto::protos::DisplayInfo& proto) { frontend::DisplayInfo displayInfo; displayInfo.info.displayId = proto.display_id(); displayInfo.info.logicalWidth = proto.logical_width(); @@ -599,10 +603,10 @@ frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo } void TransactionProtoParser::fromProto( - const google::protobuf::RepeatedPtrField& proto, + const google::protobuf::RepeatedPtrField& proto, frontend::DisplayInfos& outDisplayInfos) { outDisplayInfos.clear(); - for (const proto::DisplayInfo& displayInfo : proto) { + for (const perfetto::protos::DisplayInfo& displayInfo : proto) { outDisplayInfos.emplace_or_replace(ui::LayerStack::fromValue(displayInfo.layer_stack()), fromProto(displayInfo)); } diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h index 457c3bec40..b3ab71cfb5 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.h +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h @@ -44,25 +44,25 @@ public: TransactionProtoParser(std::unique_ptr provider) : mMapper(std::move(provider)) {} - proto::TransactionState toProto(const TransactionState&); - proto::TransactionState toProto(const std::map&); - proto::LayerCreationArgs toProto(const LayerCreationArgs& args); - proto::LayerState toProto(const ResolvedComposerState&); - static proto::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); + perfetto::protos::TransactionState toProto(const TransactionState&); + perfetto::protos::TransactionState toProto( + const std::map&); + perfetto::protos::LayerCreationArgs toProto(const LayerCreationArgs& args); + perfetto::protos::LayerState toProto(const ResolvedComposerState&); + static perfetto::protos::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); - TransactionState fromProto(const proto::TransactionState&); - void mergeFromProto(const proto::LayerState&, TracingLayerState& outState); - void fromProto(const proto::LayerCreationArgs&, LayerCreationArgs& outArgs); + TransactionState fromProto(const perfetto::protos::TransactionState&); + void mergeFromProto(const perfetto::protos::LayerState&, TracingLayerState& outState); + void fromProto(const perfetto::protos::LayerCreationArgs&, LayerCreationArgs& outArgs); std::unique_ptr mMapper; - static frontend::DisplayInfo fromProto(const proto::DisplayInfo&); - static void fromProto(const google::protobuf::RepeatedPtrField&, + static frontend::DisplayInfo fromProto(const perfetto::protos::DisplayInfo&); + static void fromProto(const google::protobuf::RepeatedPtrField&, frontend::DisplayInfos& outDisplayInfos); private: - proto::DisplayState toProto(const DisplayState&); - void fromProto(const proto::LayerState&, ResolvedComposerState& out); - DisplayState fromProto(const proto::DisplayState&); - + perfetto::protos::DisplayState toProto(const DisplayState&); + void fromProto(const perfetto::protos::LayerState&, ResolvedComposerState& out); + DisplayState fromProto(const perfetto::protos::DisplayState&); }; } // namespace android::surfaceflinger diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp index bc69191cc1..8aacbca90c 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.cpp +++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp @@ -59,7 +59,7 @@ TransactionTracing::~TransactionTracing() { status_t TransactionTracing::writeToFile(const std::string& filename) { std::scoped_lock lock(mTraceLock); - proto::TransactionTraceFile fileProto = createTraceFileProto(); + perfetto::protos::TransactionTraceFile fileProto = createTraceFileProto(); addStartingStateToProtoLocked(fileProto); return mBuffer.writeToFile(fileProto, filename); } @@ -70,10 +70,11 @@ void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) { mBuffer.setSize(mBufferSizeInBytes); } -proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { - proto::TransactionTraceFile proto; - proto.set_magic_number(uint64_t(proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 | - proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L); +perfetto::protos::TransactionTraceFile TransactionTracing::createTraceFileProto() const { + perfetto::protos::TransactionTraceFile proto; + proto.set_magic_number( + uint64_t(perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 | + perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L); auto timeOffsetNs = static_cast(systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC)); proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs); @@ -89,7 +90,8 @@ void TransactionTracing::dump(std::string& result) const { } void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) { - proto::TransactionState* state = new proto::TransactionState(mProtoParser.toProto(transaction)); + perfetto::protos::TransactionState* state = + new perfetto::protos::TransactionState(mProtoParser.toProto(transaction)); mTransactionQueue.push(state); } @@ -152,7 +154,7 @@ void TransactionTracing::addEntry(const std::vector& committed ATRACE_CALL(); std::scoped_lock lock(mTraceLock); std::vector removedEntries; - proto::TransactionTraceEntry entryProto; + perfetto::protos::TransactionTraceEntry entryProto; while (auto incomingTransaction = mTransactionQueue.pop()) { auto transaction = *incomingTransaction; @@ -211,7 +213,7 @@ void TransactionTracing::addEntry(const std::vector& committed std::make_move_iterator(entries.end())); } - proto::TransactionTraceEntry removedEntryProto; + perfetto::protos::TransactionTraceEntry removedEntryProto; for (const std::string& removedEntry : removedEntries) { removedEntryProto.ParseFromString(removedEntry); updateStartingStateLocked(removedEntryProto); @@ -236,7 +238,7 @@ void TransactionTracing::flush() { base::ScopedLockAssertion assumeLocked(mTraceLock); mTransactionsAddedToBufferCv.wait_for(lock, std::chrono::milliseconds(100), [&]() REQUIRES(mTraceLock) { - proto::TransactionTraceEntry entry; + perfetto::protos::TransactionTraceEntry entry; if (mBuffer.used() > 0) { entry.ParseFromString(mBuffer.back()); } @@ -268,19 +270,19 @@ void TransactionTracing::tryPushToTracingThread() { } void TransactionTracing::updateStartingStateLocked( - const proto::TransactionTraceEntry& removedEntry) { + const perfetto::protos::TransactionTraceEntry& removedEntry) { mStartingTimestamp = removedEntry.elapsed_realtime_nanos(); // Keep track of layer starting state so we can reconstruct the layer state as we purge // transactions from the buffer. - for (const proto::LayerCreationArgs& addedLayer : removedEntry.added_layers()) { + for (const perfetto::protos::LayerCreationArgs& addedLayer : removedEntry.added_layers()) { TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()]; startingState.layerId = addedLayer.layer_id(); mProtoParser.fromProto(addedLayer, startingState.args); } // Merge layer states to starting transaction state. - for (const proto::TransactionState& transaction : removedEntry.transactions()) { - for (const proto::LayerState& layerState : transaction.layer_changes()) { + for (const perfetto::protos::TransactionState& transaction : removedEntry.transactions()) { + for (const perfetto::protos::LayerState& layerState : transaction.layer_changes()) { auto it = mStartingStates.find(layerState.layer_id()); if (it == mStartingStates.end()) { // TODO(b/238781169) make this log fatal when we switch over to using new fe @@ -307,12 +309,13 @@ void TransactionTracing::updateStartingStateLocked( } } -void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) { +void TransactionTracing::addStartingStateToProtoLocked( + perfetto::protos::TransactionTraceFile& proto) { if (mStartingStates.size() == 0) { return; } - proto::TransactionTraceEntry* entryProto = proto.add_entry(); + perfetto::protos::TransactionTraceEntry* entryProto = proto.add_entry(); entryProto->set_elapsed_realtime_nanos(mStartingTimestamp); entryProto->set_vsync_id(0); @@ -321,7 +324,7 @@ void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFi entryProto->mutable_added_layers()->Add(mProtoParser.toProto(state.args)); } - proto::TransactionState transactionProto = mProtoParser.toProto(mStartingStates); + perfetto::protos::TransactionState transactionProto = mProtoParser.toProto(mStartingStates); transactionProto.set_vsync_id(0); transactionProto.set_post_time(mStartingTimestamp); entryProto->mutable_transactions()->Add(std::move(transactionProto)); @@ -338,9 +341,9 @@ void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFi } } -proto::TransactionTraceFile TransactionTracing::writeToProto() { +perfetto::protos::TransactionTraceFile TransactionTracing::writeToProto() { std::scoped_lock lock(mTraceLock); - proto::TransactionTraceFile proto = createTraceFileProto(); + perfetto::protos::TransactionTraceFile proto = createTraceFileProto(); addStartingStateToProtoLocked(proto); mBuffer.writeToProto(proto); return proto; diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h index 422b5f3689..09fcd8ad96 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.h +++ b/services/surfaceflinger/Tracing/TransactionTracing.h @@ -85,14 +85,16 @@ private: } mutable std::mutex mTraceLock; - TransactionRingBuffer mBuffer - GUARDED_BY(mTraceLock); + TransactionRingBuffer + mBuffer GUARDED_BY(mTraceLock); size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; - std::unordered_map mQueuedTransactions + std::unordered_map mQueuedTransactions GUARDED_BY(mTraceLock); - LocklessStack mTransactionQueue; + LocklessStack mTransactionQueue; nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock); - std::unordered_map mCreatedLayers GUARDED_BY(mTraceLock); + std::unordered_map mCreatedLayers + GUARDED_BY(mTraceLock); std::map mStartingStates GUARDED_BY(mTraceLock); frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock); @@ -122,17 +124,19 @@ private: std::vector mPendingDestroyedLayers; // only accessed by main thread int64_t mLastUpdatedVsyncId = -1; - proto::TransactionTraceFile createTraceFileProto() const; + perfetto::protos::TransactionTraceFile createTraceFileProto() const; void loop(); void addEntry(const std::vector& committedTransactions, const std::vector& removedLayers) EXCLUDES(mTraceLock); int32_t getLayerIdLocked(const sp& layerHandle) REQUIRES(mTraceLock); void tryPushToTracingThread() EXCLUDES(mMainThreadLock); - void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock); - void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock); + void addStartingStateToProtoLocked(perfetto::protos::TransactionTraceFile& proto) + REQUIRES(mTraceLock); + void updateStartingStateLocked(const perfetto::protos::TransactionTraceEntry& entry) + REQUIRES(mTraceLock); // TEST // Return buffer contents as trace file proto - proto::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); + perfetto::protos::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); }; class TransactionTraceWriter : public Singleton { diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 321b8baccc..9471e954d8 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -40,8 +40,8 @@ namespace android { using namespace ftl::flag_operators; -bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, - const char* outputLayersTracePath, bool onlyLastEntry) { +bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& traceFile, + const char*, bool onlyLastEntry) { if (traceFile.entry_size() == 0) { ALOGD("Trace file is empty"); return false; diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h index e41d1e6e0b..a1e5fc894b 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h @@ -21,7 +21,7 @@ namespace android { class LayerTraceGenerator { public: - bool generate(const proto::TransactionTraceFile&, const char* outputLayersTracePath, + bool generate(const perfetto::protos::TransactionTraceFile&, const char* outputLayersTracePath, bool onlyLastEntry); }; -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp index 5ca87e4cb3..0ff8f98d36 100644 --- a/services/surfaceflinger/Tracing/tools/main.cpp +++ b/services/surfaceflinger/Tracing/tools/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) { return -1; } - proto::TransactionTraceFile transactionTraceFile; + perfetto::protos::TransactionTraceFile transactionTraceFile; if (!transactionTraceFile.ParseFromIstream(&input)) { std::cout << "Error: Failed to parse " << transactionTracePath; return -1; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index ca1af6ed84..7ba4b24c7b 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -455,7 +455,8 @@ public: result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result); - LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); + perfetto::protos::LayersProto layersProto = + mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); mFlinger->dumpOffscreenLayersProto(layersProto); mFlinger->dumpDisplayProto(); diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index 7287dd0103..a4dc8a058e 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -13,7 +13,20 @@ cc_library { srcs: [ "LayerProtoParser.cpp", - "*.proto", + ], + + static_libs: [ + "libperfetto_client_experimental", + ], + + whole_static_libs: [ + // TODO(b/169779783): move into "static_libs" when the soong issue is fixed + "perfetto_trace_protos", + ], + + export_static_lib_headers: [ + "libperfetto_client_experimental", + "perfetto_trace_protos", ], shared_libs: [ @@ -24,10 +37,6 @@ cc_library { "libbase", ], - proto: { - export_proto_headers: true, - }, - cppflags: [ "-Werror", "-Wno-unused-parameter", @@ -42,22 +51,3 @@ cc_library { "-Wno-undef", ], } - -java_library_static { - name: "layersprotoslite", - host_supported: true, - proto: { - type: "lite", - include_dirs: ["external/protobuf/src"], - }, - srcs: ["*.proto"], - sdk_version: "core_platform", - target: { - android: { - jarjar_rules: "jarjar-rules.txt", - }, - host: { - static_libs: ["libprotobuf-java-lite"], - }, - }, -} diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 854084e7f9..8d48070e13 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -37,7 +37,8 @@ bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs return lhs->id < rhs->id; } -LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProto& layersProto) { +LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree( + const perfetto::protos::LayersProto& layersProto) { LayerTree layerTree; layerTree.allLayers = generateLayerList(layersProto); @@ -53,7 +54,7 @@ LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProt } std::vector LayerProtoParser::generateLayerList( - const LayersProto& layersProto) { + const perfetto::protos::LayersProto& layersProto) { std::vector layerList; std::unordered_map layerMap; @@ -74,7 +75,8 @@ std::vector LayerProtoParser::generateLayerList( return layerList; } -LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerProto) { +LayerProtoParser::Layer LayerProtoParser::generateLayer( + const perfetto::protos::LayerProto& layerProto) { Layer layer; layer.id = layerProto.id(); layer.name = layerProto.name(); @@ -120,17 +122,19 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP return layer; } -LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) { +LayerProtoParser::Region LayerProtoParser::generateRegion( + const perfetto::protos::RegionProto& regionProto) { LayerProtoParser::Region region; for (int i = 0; i < regionProto.rect_size(); i++) { - const RectProto& rectProto = regionProto.rect(i); + const perfetto::protos::RectProto& rectProto = regionProto.rect(i); region.rects.push_back(generateRect(rectProto)); } return region; } -LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) { +LayerProtoParser::Rect LayerProtoParser::generateRect( + const perfetto::protos::RectProto& rectProto) { LayerProtoParser::Rect rect; rect.left = rectProto.left(); rect.top = rectProto.top(); @@ -140,7 +144,8 @@ LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto return rect; } -LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) { +LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect( + const perfetto::protos::FloatRectProto& rectProto) { LayerProtoParser::FloatRect rect; rect.left = rectProto.left(); rect.top = rectProto.top(); @@ -151,7 +156,7 @@ LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectP } LayerProtoParser::Transform LayerProtoParser::generateTransform( - const TransformProto& transformProto) { + const perfetto::protos::TransformProto& transformProto) { LayerProtoParser::Transform transform; transform.dsdx = transformProto.dsdx(); transform.dtdx = transformProto.dtdx(); @@ -162,7 +167,7 @@ LayerProtoParser::Transform LayerProtoParser::generateTransform( } LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( - const ActiveBufferProto& activeBufferProto) { + const perfetto::protos::ActiveBufferProto& activeBufferProto) { LayerProtoParser::ActiveBuffer activeBuffer; activeBuffer.width = activeBufferProto.width(); activeBuffer.height = activeBufferProto.height(); @@ -172,7 +177,7 @@ LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( return activeBuffer; } -void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, +void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto, std::unordered_map& layerMap) { auto currLayer = layerMap[layerProto.id()]; diff --git a/services/surfaceflinger/layerproto/common.proto b/services/surfaceflinger/layerproto/common.proto deleted file mode 100644 index 5e20d4d0f5..0000000000 --- a/services/surfaceflinger/layerproto/common.proto +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; -package android.surfaceflinger; - -message RegionProto { - reserved 1; // Previously: uint64 id - repeated RectProto rect = 2; -} - -message RectProto { - int32 left = 1; - int32 top = 2; - int32 right = 3; - int32 bottom = 4; -} - -message SizeProto { - int32 w = 1; - int32 h = 2; -} - -message TransformProto { - float dsdx = 1; - float dtdx = 2; - float dsdy = 3; - float dtdy = 4; - int32 type = 5; -} - -message ColorProto { - float r = 1; - float g = 2; - float b = 3; - float a = 4; -} - -message InputWindowInfoProto { - uint32 layout_params_flags = 1; - int32 layout_params_type = 2; - RectProto frame = 3; - RegionProto touchable_region = 4; - - int32 surface_inset = 5; - bool visible = 6; - bool can_receive_keys = 7 [deprecated = true]; - bool focusable = 8; - bool has_wallpaper = 9; - - float global_scale_factor = 10; - float window_x_scale = 11 [deprecated = true]; - float window_y_scale = 12 [deprecated = true]; - - int32 crop_layer_id = 13; - bool replace_touchable_region_with_crop = 14; - RectProto touchable_region_crop = 15; - TransformProto transform = 16; - uint32 input_config = 17; -} - -message BlurRegion { - uint32 blur_radius = 1; - uint32 corner_radius_tl = 2; - uint32 corner_radius_tr = 3; - uint32 corner_radius_bl = 4; - float corner_radius_br = 5; - float alpha = 6; - int32 left = 7; - int32 top = 8; - int32 right = 9; - int32 bottom = 10; -} - -message ColorTransformProto { - // This will be a 4x4 matrix of float values - repeated float val = 1; -} diff --git a/services/surfaceflinger/layerproto/display.proto b/services/surfaceflinger/layerproto/display.proto deleted file mode 100644 index 64de775b8b..0000000000 --- a/services/surfaceflinger/layerproto/display.proto +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; - -package android.surfaceflinger; - -message DisplayProto { - uint64 id = 1; - - string name = 2; - - uint32 layer_stack = 3; - - SizeProto size = 4; - - RectProto layer_stack_space_rect = 5; - - TransformProto transform = 6; - - bool is_virtual = 7; - - double dpi_x = 8; - - double dpi_y = 9; -} diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h index f560562c94..4a2ef3ddf8 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h @@ -14,11 +14,14 @@ * limitations under the License. */ +#pragma once + // pragma is used here to disable the warnings emitted from the protobuf // headers. By adding #pragma before including layer.pb.h, it supresses // protobuf warnings, but allows the rest of the files to continuing using // the current flags. // This file should be included instead of directly including layer.b.h #pragma GCC system_header -#include -#include +#include +#include +#include diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index cdc2706ee2..79c3982dbd 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -131,19 +131,22 @@ public: std::vector topLevelLayers; }; - static LayerTree generateLayerTree(const LayersProto& layersProto); + static LayerTree generateLayerTree(const perfetto::protos::LayersProto& layersProto); static std::string layerTreeToString(const LayerTree& layerTree); private: - static std::vector generateLayerList(const LayersProto& layersProto); - static LayerProtoParser::Layer generateLayer(const LayerProto& layerProto); - static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); - static LayerProtoParser::Rect generateRect(const RectProto& rectProto); - static LayerProtoParser::FloatRect generateFloatRect(const FloatRectProto& rectProto); - static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); + static std::vector generateLayerList(const perfetto::protos::LayersProto& layersProto); + static LayerProtoParser::Layer generateLayer(const perfetto::protos::LayerProto& layerProto); + static LayerProtoParser::Region generateRegion( + const perfetto::protos::RegionProto& regionProto); + static LayerProtoParser::Rect generateRect(const perfetto::protos::RectProto& rectProto); + static LayerProtoParser::FloatRect generateFloatRect( + const perfetto::protos::FloatRectProto& rectProto); + static LayerProtoParser::Transform generateTransform( + const perfetto::protos::TransformProto& transformProto); static LayerProtoParser::ActiveBuffer generateActiveBuffer( - const ActiveBufferProto& activeBufferProto); - static void updateChildrenAndRelative(const LayerProto& layerProto, + const perfetto::protos::ActiveBufferProto& activeBufferProto); + static void updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto, std::unordered_map& layerMap); static std::string layerToString(const LayerProtoParser::Layer* layer); diff --git a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h index 3e9ca52fff..ea80ad8f33 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h +++ b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h @@ -14,7 +14,11 @@ * limitations under the License. */ +#pragma once + // disable the warnings emitted from the protobuf headers. This file should be included instead of // directly including the generated header file #pragma GCC system_header -#include +#include +#include +#include diff --git a/services/surfaceflinger/layerproto/jarjar-rules.txt b/services/surfaceflinger/layerproto/jarjar-rules.txt deleted file mode 100644 index 40043a861c..0000000000 --- a/services/surfaceflinger/layerproto/jarjar-rules.txt +++ /dev/null @@ -1 +0,0 @@ -rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto deleted file mode 100644 index e9add2e1a4..0000000000 --- a/services/surfaceflinger/layerproto/layers.proto +++ /dev/null @@ -1,171 +0,0 @@ -// Definitions for SurfaceFlinger layers. - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; - -package android.surfaceflinger; - -// Contains a list of all layers. -message LayersProto { - repeated LayerProto layers = 1; -} - -// Must match definition in the IComposerClient HAL -enum HwcCompositionType { - // Invalid composition type - INVALID = 0; - // Layer was composited by the client into the client target buffer - CLIENT = 1; - // Layer was composited by the device through hardware overlays - DEVICE = 2; - // Layer was composited by the device using a color - SOLID_COLOR = 3; - // Similar to DEVICE, but the layer position may have been asynchronously set - // through setCursorPosition - CURSOR = 4; - // Layer was composited by the device via a sideband stream. - SIDEBAND = 5; -} - -// Information about each layer. -message LayerProto { - // unique id per layer. - int32 id = 1; - // unique name per layer. - string name = 2; - // list of children this layer may have. May be empty. - repeated int32 children = 3; - // list of layers that are z order relative to this layer. - repeated int32 relatives = 4; - // The type of layer, ex Color, Layer - string type = 5; - RegionProto transparent_region = 6; - RegionProto visible_region = 7; - RegionProto damage_region = 8; - uint32 layer_stack = 9; - // The layer's z order. Can be z order in layer stack, relative to parent, - // or relative to another layer specified in zOrderRelative. - int32 z = 10; - // The layer's position on the display. - PositionProto position = 11; - // The layer's requested position. - PositionProto requested_position = 12; - // The layer's size. - SizeProto size = 13; - // The layer's crop in it's own bounds. - RectProto crop = 14; - // The layer's crop in it's parent's bounds. - RectProto final_crop = 15 [deprecated=true]; - bool is_opaque = 16; - bool invalidate = 17; - string dataspace = 18; - string pixel_format = 19; - // The layer's actual color. - ColorProto color = 20; - // The layer's requested color. - ColorProto requested_color = 21; - // Can be any combination of - // hidden = 0x01 - // opaque = 0x02, - // secure = 0x80, - uint32 flags = 22; - // The layer's actual transform - TransformProto transform = 23; - // The layer's requested transform. - TransformProto requested_transform = 24; - // The parent layer. This value can be null if there is no parent. - int32 parent = 25; - // The layer that this layer has a z order relative to. This value can be null. - int32 z_order_relative_of = 26; - // This value can be null if there's nothing to draw. - ActiveBufferProto active_buffer = 27; - // The number of frames available. - int32 queued_frames = 28; - bool refresh_pending = 29; - // The layer's composer backend destination frame - RectProto hwc_frame = 30; - // The layer's composer backend source crop - FloatRectProto hwc_crop = 31; - // The layer's composer backend transform - int32 hwc_transform = 32; - int32 window_type = 33 [deprecated=true]; - int32 app_id = 34 [deprecated=true]; - // The layer's composition type - HwcCompositionType hwc_composition_type = 35; - // If it's a buffer layer, indicate if the content is protected - bool is_protected = 36; - // Current frame number being rendered. - uint64 curr_frame = 37; - // A list of barriers that the layer is waiting to update state. - repeated BarrierLayerProto barrier_layer = 38; - // If active_buffer is not null, record its transform. - TransformProto buffer_transform = 39; - int32 effective_scaling_mode = 40; - // Layer's corner radius. - float corner_radius = 41; - // Metadata map. May be empty. - map metadata = 42; - - TransformProto effective_transform = 43; - FloatRectProto source_bounds = 44; - FloatRectProto bounds = 45; - FloatRectProto screen_bounds = 46; - - InputWindowInfoProto input_window_info = 47; - - // Crop used to draw the rounded corner. - FloatRectProto corner_radius_crop = 48; - - // length of the shadow to draw around the layer, it may be set on the - // layer or set by a parent layer. - float shadow_radius = 49; - ColorTransformProto color_transform = 50; - - bool is_relative_of = 51; - // Layer's background blur radius in pixels. - int32 background_blur_radius = 52; - - uint32 owner_uid = 53; - - // Regions of a layer, where blur should be applied. - repeated BlurRegion blur_regions = 54; - - bool is_trusted_overlay = 55; - - // Corner radius explicitly set on layer rather than inherited - float requested_corner_radius = 56; - - RectProto destination_frame = 57; - - uint32 original_id = 58; -} - -message PositionProto { - float x = 1; - float y = 2; -} - -message FloatRectProto { - float left = 1; - float top = 2; - float right = 3; - float bottom = 4; -} - -message ActiveBufferProto { - uint32 width = 1; - uint32 height = 2; - uint32 stride = 3; - int32 format = 4; - uint64 usage = 5; -} - -message BarrierLayerProto { - // layer id the barrier is waiting on. - int32 id = 1; - // frame number the barrier is waiting on. - uint64 frame_number = 2; -} - diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto deleted file mode 100644 index 804a4994ee..0000000000 --- a/services/surfaceflinger/layerproto/layerstrace.proto +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/layers.proto"; -import "frameworks/native/services/surfaceflinger/layerproto/display.proto"; - -package android.surfaceflinger; - -/* represents a file full of surface flinger trace entries. - Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such - that they can be easily identified. */ -message LayersTraceFileProto { - - /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L - (this is needed because enums have to be 32 bits and there's no nice way to put 64bit - constants into .proto files. */ - enum MagicNumber { - INVALID = 0; - MAGIC_NUMBER_L = 0x5452594c; /* LYRT (little-endian ASCII) */ - MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ - } - - optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ - repeated LayersTraceProto entry = 2; - - /* offset between real-time clock and elapsed time clock in nanoseconds. - Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */ - optional fixed64 real_to_elapsed_time_offset_nanos = 3; -} - -/* one layers trace entry. */ -message LayersTraceProto { - /* required: elapsed realtime in nanos since boot of when this entry was logged */ - optional sfixed64 elapsed_realtime_nanos = 1; - - /* where the trace originated */ - optional string where = 2; - - optional LayersProto layers = 3; - - // Blob for the current HWC information for all layers, reported by dumpsys. - optional string hwc_blob = 4; - - /* Includes state sent during composition like visible region and composition type. */ - optional bool excludes_composition_state = 5; - - /* Number of missed entries since the last entry was recorded. */ - optional uint32 missed_entries = 6; - - repeated DisplayProto displays = 7; - - optional int64 vsync_id = 8; -} diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto deleted file mode 100644 index d03afa05ab..0000000000 --- a/services/surfaceflinger/layerproto/transactions.proto +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; - -package android.surfaceflinger.proto; - -/* Represents a file full of surface flinger transactions. - Encoded, it should start with 0x54 0x4E 0x58 0x54 0x52 0x41 0x43 0x45 (.TNXTRACE), such - that they can be easily identified. */ -message TransactionTraceFile { - /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L - (this is needed because enums have to be 32 bits and there's no nice way to put 64bit - constants into .proto files. */ - enum MagicNumber { - INVALID = 0; - MAGIC_NUMBER_L = 0x54584E54; /* TNXT (little-endian ASCII) */ - MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ - } - - fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ - repeated TransactionTraceEntry entry = 2; - - /* offset between real-time clock and elapsed time clock in nanoseconds. - Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */ - fixed64 real_to_elapsed_time_offset_nanos = 3; - uint32 version = 4; -} - -message TransactionTraceEntry { - int64 elapsed_realtime_nanos = 1; - int64 vsync_id = 2; - repeated TransactionState transactions = 3; - repeated LayerCreationArgs added_layers = 4; - repeated uint32 destroyed_layers = 5; - repeated DisplayState added_displays = 6; - repeated int32 removed_displays = 7; - repeated uint32 destroyed_layer_handles = 8; - bool displays_changed = 9; - repeated DisplayInfo displays = 10; -} - -message DisplayInfo { - uint32 layer_stack = 1; - int32 display_id = 2; - int32 logical_width = 3; - int32 logical_height = 4; - Transform transform_inverse = 5; - Transform transform = 6; - bool receives_input = 7; - bool is_secure = 8; - bool is_primary = 9; - bool is_virtual = 10; - int32 rotation_flags = 11; - int32 transform_hint = 12; - -} - -message LayerCreationArgs { - uint32 layer_id = 1; - string name = 2; - uint32 flags = 3; - uint32 parent_id = 4; - uint32 mirror_from_id = 5; - bool add_to_root = 6; - uint32 layer_stack_to_mirror = 7; -} - -message Transform { - float dsdx = 1; - float dtdx = 2; - float dtdy = 3; - float dsdy = 4; - float tx = 5; - float ty = 6; -} - -message TransactionState { - int32 pid = 1; - int32 uid = 2; - int64 vsync_id = 3; - int32 input_event_id = 4; - int64 post_time = 5; - uint64 transaction_id = 6; - repeated LayerState layer_changes = 7; - repeated DisplayState display_changes = 8; - repeated uint64 merged_transaction_ids = 9; -} - -// Keep insync with layer_state_t -message LayerState { - uint32 layer_id = 1; - // Changes are split into ChangesLsb and ChangesMsb. First 32 bits are in ChangesLsb - // and the next 32 bits are in ChangesMsb. This is needed because enums have to be - // 32 bits and there's no nice way to put 64bit constants into .proto files. - enum ChangesLsb { - eChangesLsbNone = 0; - ePositionChanged = 0x00000001; - eLayerChanged = 0x00000002; - // unused = 0x00000004; - eAlphaChanged = 0x00000008; - - eMatrixChanged = 0x00000010; - eTransparentRegionChanged = 0x00000020; - eFlagsChanged = 0x00000040; - eLayerStackChanged = 0x00000080; - - eReleaseBufferListenerChanged = 0x00000400; - eShadowRadiusChanged = 0x00000800; - - eBufferCropChanged = 0x00002000; - eRelativeLayerChanged = 0x00004000; - eReparent = 0x00008000; - - eColorChanged = 0x00010000; - eBufferTransformChanged = 0x00040000; - eTransformToDisplayInverseChanged = 0x00080000; - - eCropChanged = 0x00100000; - eBufferChanged = 0x00200000; - eAcquireFenceChanged = 0x00400000; - eDataspaceChanged = 0x00800000; - - eHdrMetadataChanged = 0x01000000; - eSurfaceDamageRegionChanged = 0x02000000; - eApiChanged = 0x04000000; - eSidebandStreamChanged = 0x08000000; - - eColorTransformChanged = 0x10000000; - eHasListenerCallbacksChanged = 0x20000000; - eInputInfoChanged = 0x40000000; - eCornerRadiusChanged = -2147483648; // 0x80000000; (proto stores enums as signed int) - }; - enum ChangesMsb { - eChangesMsbNone = 0; - eDestinationFrameChanged = 0x1; - eCachedBufferChanged = 0x2; - eBackgroundColorChanged = 0x4; - eMetadataChanged = 0x8; - eColorSpaceAgnosticChanged = 0x10; - eFrameRateSelectionPriority = 0x20; - eFrameRateChanged = 0x40; - eBackgroundBlurRadiusChanged = 0x80; - eProducerDisconnect = 0x100; - eFixedTransformHintChanged = 0x200; - eFrameNumberChanged = 0x400; - eBlurRegionsChanged = 0x800; - eAutoRefreshChanged = 0x1000; - eStretchChanged = 0x2000; - eTrustedOverlayChanged = 0x4000; - eDropInputModeChanged = 0x8000; - }; - uint64 what = 2; - float x = 3; - float y = 4; - int32 z = 5; - uint32 w = 6; - uint32 h = 7; - uint32 layer_stack = 8; - - enum Flags { - eFlagsNone = 0; - eLayerHidden = 0x01; - eLayerOpaque = 0x02; - eLayerSkipScreenshot = 0x40; - eLayerSecure = 0x80; - eEnableBackpressure = 0x100; - eLayerIsDisplayDecoration = 0x200; - }; - uint32 flags = 9; - uint32 mask = 10; - - message Matrix22 { - float dsdx = 1; - float dtdx = 2; - float dtdy = 3; - float dsdy = 4; - }; - Matrix22 matrix = 11; - float corner_radius = 12; - uint32 background_blur_radius = 13; - uint32 parent_id = 14; - uint32 relative_parent_id = 15; - - float alpha = 16; - message Color3 { - float r = 1; - float g = 2; - float b = 3; - } - Color3 color = 17; - RegionProto transparent_region = 18; - uint32 transform = 19; - bool transform_to_display_inverse = 20; - RectProto crop = 21; - - message BufferData { - uint64 buffer_id = 1; - uint32 width = 2; - uint32 height = 3; - uint64 frame_number = 4; - - enum BufferDataChange { - BufferDataChangeNone = 0; - fenceChanged = 0x01; - frameNumberChanged = 0x02; - cachedBufferChanged = 0x04; - } - uint32 flags = 5; - uint64 cached_buffer_id = 6; - - enum PixelFormat { - PIXEL_FORMAT_UNKNOWN = 0; - PIXEL_FORMAT_CUSTOM = -4; - PIXEL_FORMAT_TRANSLUCENT = -3; - PIXEL_FORMAT_TRANSPARENT = -2; - PIXEL_FORMAT_OPAQUE = -1; - PIXEL_FORMAT_RGBA_8888 = 1; - PIXEL_FORMAT_RGBX_8888 = 2; - PIXEL_FORMAT_RGB_888 = 3; - PIXEL_FORMAT_RGB_565 = 4; - PIXEL_FORMAT_BGRA_8888 = 5; - PIXEL_FORMAT_RGBA_5551 = 6; - PIXEL_FORMAT_RGBA_4444 = 7; - PIXEL_FORMAT_RGBA_FP16 = 22; - PIXEL_FORMAT_RGBA_1010102 = 43; - PIXEL_FORMAT_R_8 = 0x38; - } - PixelFormat pixel_format = 7; - uint64 usage = 8; - } - BufferData buffer_data = 22; - int32 api = 23; - bool has_sideband_stream = 24; - ColorTransformProto color_transform = 25; - repeated BlurRegion blur_regions = 26; - - message WindowInfo { - uint32 layout_params_flags = 1; - int32 layout_params_type = 2; - RegionProto touchable_region = 3; - int32 surface_inset = 4; - bool focusable = 5; // unused - bool has_wallpaper = 6; // unused - float global_scale_factor = 7; - uint32 crop_layer_id = 8; - bool replace_touchable_region_with_crop = 9; - RectProto touchable_region_crop = 10; - Transform transform = 11; - uint32 input_config = 12; - } - WindowInfo window_info_handle = 27; - float bg_color_alpha = 28; - int32 bg_color_dataspace = 29; - bool color_space_agnostic = 30; - float shadow_radius = 31; - int32 frame_rate_selection_priority = 32; - float frame_rate = 33; - int32 frame_rate_compatibility = 34; - int32 change_frame_rate_strategy = 35; - uint32 fixed_transform_hint = 36; - uint64 frame_number = 37; - bool auto_refresh = 38; - bool is_trusted_overlay = 39; - RectProto buffer_crop = 40; - RectProto destination_frame = 41; - - enum DropInputMode { - NONE = 0; - ALL = 1; - OBSCURED = 2; - }; - DropInputMode drop_input_mode = 42; -} - -message DisplayState { - enum Changes { - eChangesNone = 0; - eSurfaceChanged = 0x01; - eLayerStackChanged = 0x02; - eDisplayProjectionChanged = 0x04; - eDisplaySizeChanged = 0x08; - eFlagsChanged = 0x10; - }; - int32 id = 1; - uint32 what = 2; - uint32 flags = 3; - uint32 layer_stack = 4; - uint32 orientation = 5; - RectProto layer_stack_space_rect = 6; - RectProto oriented_display_space_rect = 7; - uint32 width = 8; - uint32 height = 9; -} diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index 03201f7937..b30df5ef15 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -51,9 +51,9 @@ TEST(SurfaceFlingerStress, create_and_destroy) { } } -surfaceflinger::LayersProto generateLayerProto() { - surfaceflinger::LayersProto layersProto; - std::array layers = {}; +perfetto::protos::LayersProto generateLayerProto() { + perfetto::protos::LayersProto layersProto; + std::array layers = {}; for (size_t i = 0; i < layers.size(); ++i) { layers[i] = layersProto.add_layers(); layers[i]->set_id(i); @@ -103,7 +103,7 @@ TEST(LayerProtoStress, mem_info) { cmd += std::to_string(getpid()); system(cmd.c_str()); for (int i = 0; i < 100000; i++) { - surfaceflinger::LayersProto layersProto = generateLayerProto(); + perfetto::protos::LayersProto layersProto = generateLayerProto(); auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto); surfaceflinger::LayerProtoParser::layerTreeToString(layerTree); } diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp index b8a5e79a38..333768a92a 100644 --- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp +++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp @@ -149,7 +149,7 @@ static LayerInfo getLayerInfoFromProto(::android::surfaceflinger::LayerProto& pr } static std::vector getLayerInfosFromProto( - android::surfaceflinger::LayersTraceProto& entry) { + perfetto::protos::pbzero::LayersSnapshotProto& entry) { std::unordered_map snapshotIdToLayerId; std::vector layers; layers.reserve(static_cast(entry.layers().layers_size())); @@ -267,4 +267,4 @@ int main(int argc, char** argv) { } ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +} diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp index a95a6453d5..cbb597af69 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -85,7 +85,7 @@ TEST(TransactionProtoParserTest, parse) { TransactionProtoParser parser(std::make_unique(displayHandle)); - proto::TransactionState proto = parser.toProto(t1); + perfetto::protos::TransactionState proto = parser.toProto(t1); TransactionState t2 = parser.fromProto(proto); ASSERT_EQ(t1.originPid, t2.originPid); @@ -119,7 +119,7 @@ TEST(TransactionProtoParserTest, parseDisplayInfo) { d1.transformHint = ui::Transform::ROT_90; const uint32_t layerStack = 2; - google::protobuf::RepeatedPtrField displayProtos; + google::protobuf::RepeatedPtrField displayProtos; auto displayInfoProto = displayProtos.Add(); *displayInfoProto = TransactionProtoParser::toProto(d1, layerStack); frontend::DisplayInfos displayInfos; diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp index 71a2d2b9a6..7981224b5c 100644 --- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp @@ -37,11 +37,11 @@ protected: TransactionTracing mTracing; void flush() { mTracing.flush(); } - proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } + perfetto::protos::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } - proto::TransactionTraceEntry bufferFront() { + perfetto::protos::TransactionTraceEntry bufferFront() { std::scoped_lock lock(mTracing.mTraceLock); - proto::TransactionTraceEntry entry; + perfetto::protos::TransactionTraceEntry entry; entry.ParseFromString(mTracing.mBuffer.front()); return entry; } @@ -59,7 +59,7 @@ protected: flush(); } - void verifyEntry(const proto::TransactionTraceEntry& actualProto, + void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto, const std::vector& expectedTransactions, int64_t expectedVsyncId) { EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId); @@ -117,7 +117,7 @@ TEST_F(TransactionTracingTest, addTransactions) { mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false); flush(); - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); ASSERT_EQ(proto.entry().size(), 2); verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId); verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId); @@ -203,7 +203,7 @@ TEST_F(TransactionTracingLayerHandlingTest, addStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify we can still retrieve the layer change from the first entry containing starting // states. EXPECT_GT(proto.entry().size(), 0); @@ -221,7 +221,7 @@ TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify starting states are updated correctly EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41); } @@ -231,7 +231,7 @@ TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify the child layer has been removed from the trace EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1); EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId); @@ -242,7 +242,7 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) { while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify we have two starting states EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2); @@ -302,7 +302,7 @@ protected: }; TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // We don't have any starting states since no layer was removed from. EXPECT_EQ(proto.entry().size(), 1); @@ -317,18 +317,18 @@ TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { // Verify we can write the layers traces by entry to reduce mem pressure // on the system when generating large traces. TEST(LayerTraceTest, canStreamLayersTrace) { - LayersTraceFileProto inProto = LayerTracing::createTraceFileProto(); + perfetto::protos::LayersTraceFileProto inProto = LayerTracing::createTraceFileProto(); inProto.add_entry(); inProto.add_entry(); std::string output; inProto.SerializeToString(&output); - LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto(); + perfetto::protos::LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto(); inProto2.add_entry(); std::string output2; inProto2.SerializeToString(&output2); - LayersTraceFileProto outProto; + perfetto::protos::LayersTraceFileProto outProto; outProto.ParseFromString(output + output2); // magic? EXPECT_EQ(outProto.entry().size(), 3); -- cgit v1.2.3-59-g8ed1b From 5dad909092932dc5c02d1be2f6ece1a3d06908ad Mon Sep 17 00:00:00 2001 From: Kean Mariotti Date: Thu, 27 Apr 2023 16:42:13 +0000 Subject: Revert layer proto format back to proto2 Perfetto doesn't support proto3, hence reverted to proto2. This reverts commit dcc0bab76dbf3156f18e4dd2697aa7220ad7a8e0 Bug: b/284424784 Test: atest libsurfaceflinger_unittest && atest transactiontrace_testsuite Change-Id: Ibfc5442c18a3431098eefc53a023f6e66afc7c26 --- services/surfaceflinger/Layer.cpp | 4 ---- services/surfaceflinger/layerproto/LayerProtoParser.cpp | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 075ea00134..f0643fa48d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2312,15 +2312,11 @@ void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote(); if (parent != nullptr) { layerInfo->set_parent(parent->sequence); - } else { - layerInfo->set_parent(-1); } auto zOrderRelativeOf = state.zOrderRelativeOf.promote(); if (zOrderRelativeOf != nullptr) { layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); - } else { - layerInfo->set_z_order_relative_of(-1); } layerInfo->set_is_relative_of(state.isRelativeOf); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 8d48070e13..c3d0a40261 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -193,13 +193,13 @@ void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerPr } } - if (layerProto.parent() != -1) { + if (layerProto.has_parent()) { if (layerMap.count(layerProto.parent()) > 0) { currLayer->parent = layerMap[layerProto.parent()]; } } - if (layerProto.z_order_relative_of() != -1) { + if (layerProto.has_z_order_relative_of()) { if (layerMap.count(layerProto.z_order_relative_of()) > 0) { currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()]; } -- cgit v1.2.3-59-g8ed1b From c70bee298f8faaccf4d158048f0bdd49a819f4a5 Mon Sep 17 00:00:00 2001 From: Arthur Hung Date: Fri, 2 Jun 2023 01:35:52 +0000 Subject: SF: Suppress frame rate when small area updating The small area is defined as the area that user is hard to obvious the content updating such as small icon animtion or progress bar. When content detect frame rate feature is enabled, and no explict refresh vote is set to the layer, it will heuristically calculate the predict frame rate by counting the average frame time of recent frames. This CL will enhance the contect detection by checking the small dirty frames and supress the predict frame rate that could prevent the app always running at max frame rate cause unexcpected battery consumption. This will cover 2 use cases: 1. When a layer contains a textureview, it will enter the heuristic calcuation, and this would skip the small dirty frames and supress the calculated frame rate not always to be max. 2. When an app has the separated video surface and ui surface, and the video had set an explicit rate by the content, this will ignore the heristic calculation for ui layer when it detected the small dirty frames, so the final refresh rate selection could mainly rely on the weight of the video layer. Bug: 281720315 Test: atest LayerHistoryTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:65705849c4f6339ade986bd0745ea5470ba76ebb) Merged-In: I9731de8adf8e68b72326b195fa720d51e02bae74 Change-Id: I9731de8adf8e68b72326b195fa720d51e02bae74 --- services/surfaceflinger/Layer.cpp | 56 +++++++++++++++++ services/surfaceflinger/Layer.h | 12 ++++ services/surfaceflinger/Scheduler/LayerHistory.cpp | 7 +++ services/surfaceflinger/Scheduler/LayerHistory.h | 5 ++ services/surfaceflinger/Scheduler/LayerInfo.cpp | 30 ++++++++- services/surfaceflinger/Scheduler/LayerInfo.h | 12 +++- services/surfaceflinger/Scheduler/Scheduler.h | 10 +++ .../Scheduler/include/scheduler/Features.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 12 ++++ .../tests/unittests/LayerHistoryTest.cpp | 71 ++++++++++++++++++++++ 10 files changed, 213 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 50f24a7702..8f785a044c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3212,6 +3212,14 @@ bool Layer::setBuffer(std::shared_ptr& buffer, } mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint; + + // If the layer had been updated a TextureView, this would make sure the present time could be + // same to TextureView update when it's a small dirty, and get the correct heuristic rate. + if (mFlinger->mScheduler->supportSmallDirtyDetection()) { + if (mDrawingState.useVsyncIdForRefreshRateSelection) { + mUsedVsyncIdForRefreshRateSelection = true; + } + } return true; } @@ -3234,10 +3242,38 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro mDrawingState.latchedVsyncId); if (prediction.has_value()) { ATRACE_FORMAT_INSTANT("predictedPresentTime"); + mMaxTimeForUseVsyncId = prediction->presentTime + + scheduler::LayerHistory::kMaxPeriodForHistory.count(); return prediction->presentTime; } } + if (!mFlinger->mScheduler->supportSmallDirtyDetection()) { + return static_cast(0); + } + + // If the layer is not an application and didn't set an explicit rate or desiredPresentTime, + // return "0" to tell the layer history that it will use the max refresh rate without + // calculating the adaptive rate. + if (mWindowType != WindowInfo::Type::APPLICATION && + mWindowType != WindowInfo::Type::BASE_APPLICATION) { + return static_cast(0); + } + + // Return the valid present time only when the layer potentially updated a TextureView so + // LayerHistory could heuristically calculate the rate if the UI is continually updating. + if (mUsedVsyncIdForRefreshRateSelection) { + const auto prediction = + mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken( + mDrawingState.latchedVsyncId); + if (prediction.has_value()) { + if (mMaxTimeForUseVsyncId >= prediction->presentTime) { + return prediction->presentTime; + } + mUsedVsyncIdForRefreshRateSelection = false; + } + } + return static_cast(0); }(); @@ -3297,6 +3333,7 @@ bool Layer::setSurfaceDamageRegion(const Region& surfaceDamage) { mDrawingState.surfaceDamageRegion = surfaceDamage; mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); + setIsSmallDirty(); return true; } @@ -4335,6 +4372,25 @@ void Layer::updateLastLatchTime(nsecs_t latchTime) { mLastLatchTime = latchTime; } +void Layer::setIsSmallDirty() { + if (!mFlinger->mScheduler->supportSmallDirtyDetection()) { + return; + } + + if (mWindowType != WindowInfo::Type::APPLICATION && + mWindowType != WindowInfo::Type::BASE_APPLICATION) { + return; + } + Rect bounds = mDrawingState.surfaceDamageRegion.getBounds(); + if (!bounds.isValid()) { + return; + } + + // If the damage region is a small dirty, this could give the hint for the layer history that + // it could suppress the heuristic rate when calculating. + mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(bounds.getWidth() * bounds.getHeight()); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 1f2485fafe..7b6c56b6a8 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -841,6 +841,14 @@ public: mutable bool contentDirty{false}; Region surfaceDamageRegion; + // True when the surfaceDamageRegion is recognized as a small area update. + bool mSmallDirty{false}; + // Used to check if mUsedVsyncIdForRefreshRateSelection should be expired when it stop updating. + nsecs_t mMaxTimeForUseVsyncId = 0; + // True when DrawState.useVsyncIdForRefreshRateSelection previously set to true during updating + // buffer. + bool mUsedVsyncIdForRefreshRateSelection{false}; + // Layer serial number. This gives layers an explicit ordering, so we // have a stable sort order when their layer stack and Z-order are // the same. @@ -903,6 +911,7 @@ public: .transform = getTransform(), .setFrameRateVote = getFrameRateForLayerTree(), .frameRateSelectionPriority = getFrameRateSelectionPriority(), + .isSmallDirty = mSmallDirty, }; }; bool hasBuffer() const { return mBufferInfo.mBuffer != nullptr; } @@ -917,6 +926,9 @@ public: // Exposed so SurfaceFlinger can assert that it's held const sp mFlinger; + // Check if the damage region is a small dirty. + void setIsSmallDirty(); + protected: // For unit tests friend class TestableSurfaceFlinger; diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 565a490ec8..13cf764746 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -306,4 +306,11 @@ auto LayerHistory::findLayer(int32_t id) -> std::pair { return {LayerStatus::NotFound, nullptr}; } +bool LayerHistory::isSmallDirtyArea(uint32_t dirtyArea) const { + const float ratio = (float)dirtyArea / mDisplayArea; + const bool isSmallDirty = ratio <= kSmallDirtyArea; + ATRACE_FORMAT_INSTANT("small dirty=%s, ratio=%.3f", isSmallDirty ? "true" : "false", ratio); + return isSmallDirty; +} + } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index d083fa2955..562bb4cace 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -43,6 +43,7 @@ struct LayerProps; class LayerHistory { public: using LayerVoteType = RefreshRateSelector::LayerVoteType; + static constexpr std::chrono::nanoseconds kMaxPeriodForHistory = 1s; LayerHistory(); ~LayerHistory(); @@ -84,10 +85,14 @@ public: // return the frames per second of the layer with the given sequence id. float getLayerFramerate(nsecs_t now, int32_t id) const; + bool isSmallDirtyArea(uint32_t dirtyArea) const; + private: friend class LayerHistoryTest; friend class TestableScheduler; + static constexpr float kSmallDirtyArea = 0.07f; + using LayerPair = std::pair>; // keyed by id as returned from Layer::getSequence() using LayerInfos = std::unordered_map; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 750803b2f9..e4df494f66 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -65,7 +65,8 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUp case LayerUpdateType::Buffer: FrameTimeData frameTime = {.presentTime = lastPresentTime, .queueTime = mLastUpdatedTime, - .pendingModeChange = pendingModeChange}; + .pendingModeChange = pendingModeChange, + .isSmallDirty = props.isSmallDirty}; mFrameTimes.push_back(frameTime); if (mFrameTimes.size() > HISTORY_SIZE) { mFrameTimes.pop_front(); @@ -101,11 +102,15 @@ LayerInfo::Frequent LayerInfo::isFrequent(nsecs_t now) const { // classification. bool isFrequent = true; bool isInfrequent = true; + int32_t smallDirtyCount = 0; const auto n = mFrameTimes.size() - 1; for (size_t i = 0; i < kFrequentLayerWindowSize - 1; i++) { if (mFrameTimes[n - i].queueTime - mFrameTimes[n - i - 1].queueTime < kMaxPeriodForFrequentLayerNs.count()) { isInfrequent = false; + if (mFrameTimes[n - i].presentTime == 0 && mFrameTimes[n - i].isSmallDirty) { + smallDirtyCount++; + } } else { isFrequent = false; } @@ -115,7 +120,8 @@ LayerInfo::Frequent LayerInfo::isFrequent(nsecs_t now) const { // If the layer was previously inconclusive, we clear // the history as indeterminate layers changed to frequent, // and we should not look at the stale data. - return {isFrequent, isFrequent && !mIsFrequencyConclusive, /* isConclusive */ true}; + return {isFrequent, isFrequent && !mIsFrequencyConclusive, /* isConclusive */ true, + /* isSmallDirty */ smallDirtyCount >= kNumSmallDirtyThreshold}; } // If we can't determine whether the layer is frequent or not, we return @@ -204,6 +210,7 @@ std::optional LayerInfo::calculateAverageFrameTime() const { nsecs_t totalDeltas = 0; int numDeltas = 0; + int32_t smallDirtyCount = 0; auto prevFrame = mFrameTimes.begin(); for (auto it = mFrameTimes.begin() + 1; it != mFrameTimes.end(); ++it) { const auto currDelta = getFrameTime(*it) - getFrameTime(*prevFrame); @@ -212,6 +219,13 @@ std::optional LayerInfo::calculateAverageFrameTime() const { continue; } + // If this is a small area update, we don't want to consider it for calculating the average + // frame time. Instead, we let the bigger frame updates to drive the calculation. + if (it->isSmallDirty && currDelta < kMinPeriodBetweenSmallDirtyFrames) { + smallDirtyCount++; + continue; + } + prevFrame = it; if (currDelta > kMaxPeriodBetweenFrames) { @@ -223,6 +237,10 @@ std::optional LayerInfo::calculateAverageFrameTime() const { numDeltas++; } + if (smallDirtyCount > 0) { + ATRACE_FORMAT_INSTANT("small dirty = %" PRIu32, smallDirtyCount); + } + if (numDeltas == 0) { return std::nullopt; } @@ -313,6 +331,14 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec clearHistory(now); } + // Return no vote if the latest frames are small dirty. + if (frequent.isSmallDirty && !mLastRefreshRate.reported.isValid()) { + ATRACE_FORMAT_INSTANT("NoVote (small dirty)"); + ALOGV("%s is small dirty", mName.c_str()); + votes.push_back({LayerHistory::LayerVoteType::NoVote, Fps()}); + return votes; + } + auto refreshRate = calculateRefreshRateIfPossible(selector, now); if (refreshRate.has_value()) { ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str()); diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 7d2444c94b..1e08ec8a83 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -58,6 +58,7 @@ class LayerInfo { static constexpr Fps kMinFpsForFrequentLayer = 10_Hz; static constexpr auto kMaxPeriodForFrequentLayerNs = std::chrono::nanoseconds(kMinFpsForFrequentLayer.getPeriodNsecs()) + 1ms; + static constexpr size_t kNumSmallDirtyThreshold = 2; friend class LayerHistoryTest; friend class LayerInfoTest; @@ -235,6 +236,7 @@ private: nsecs_t presentTime; // desiredPresentTime, if provided nsecs_t queueTime; // buffer queue time bool pendingModeChange; + bool isSmallDirty; }; // Holds information about the calculated and reported refresh rate @@ -299,6 +301,8 @@ private: bool clearHistory; // Represents whether we were able to determine isFrequent conclusively bool isConclusive; + // Represents whether the latest frames are small dirty. + bool isSmallDirty = false; }; Frequent isFrequent(nsecs_t now) const; bool isAnimating(nsecs_t now) const; @@ -317,6 +321,11 @@ private: // this period apart from each other, the interval between them won't be // taken into account when calculating average frame rate. static constexpr nsecs_t kMaxPeriodBetweenFrames = kMinFpsForFrequentLayer.getPeriodNsecs(); + // Used for sanitizing the heuristic data. If frames are small dirty updating and are less + // than this period apart from each other, the interval between them won't be + // taken into account when calculating average frame rate. + static constexpr nsecs_t kMinPeriodBetweenSmallDirtyFrames = (60_Hz).getPeriodNsecs(); + LayerHistory::LayerVoteType mDefaultVote; LayerVote mLayerVote; @@ -331,7 +340,7 @@ private: std::chrono::time_point mFrameTimeValidSince = std::chrono::steady_clock::now(); static constexpr size_t HISTORY_SIZE = RefreshRateHistory::HISTORY_SIZE; - static constexpr std::chrono::nanoseconds HISTORY_DURATION = 1s; + static constexpr std::chrono::nanoseconds HISTORY_DURATION = LayerHistory::kMaxPeriodForHistory; std::unique_ptr mLayerProps; @@ -349,6 +358,7 @@ struct LayerProps { ui::Transform transform; LayerInfo::FrameRate setFrameRateVote; int32_t frameRateSelectionPriority = -1; + bool isSmallDirty = false; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 85d0f9add5..ec20610f81 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -309,6 +309,16 @@ public: bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) EXCLUDES(mPolicyLock); + // Returns true if the small dirty detection is enabled. + bool supportSmallDirtyDetection() const { + return mFeatures.test(Feature::kSmallDirtyContentDetection); + } + + // Returns true if the dirty area is less than threshold. + bool isSmallDirtyArea(uint32_t dirtyArea) const { + return mLayerHistory.isSmallDirtyArea(dirtyArea); + } + private: friend class TestableScheduler; diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Features.h b/services/surfaceflinger/Scheduler/include/scheduler/Features.h index 200407d1a6..7c72ac6afc 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/Features.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/Features.h @@ -28,6 +28,7 @@ enum class Feature : std::uint8_t { kContentDetection = 1 << 2, kTracePredictedVsync = 1 << 3, kBackpressureGpuComposition = 1 << 4, + kSmallDirtyContentDetection = 1 << 5, }; using FeatureFlags = ftl::Flags; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cb8edc38ca..940a4c6b66 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3989,6 +3989,9 @@ void SurfaceFlinger::initScheduler(const sp& display) { if (sysprop::use_content_detection_for_refresh_rate(false)) { features |= Feature::kContentDetection; + if (base::GetBoolProperty("debug.sf.enable_small_dirty_detection"s, false)) { + features |= Feature::kSmallDirtyContentDetection; + } } if (base::GetBoolProperty("debug.sf.show_predicted_vsync"s, false)) { features |= Feature::kTracePredictedVsync; @@ -8334,6 +8337,15 @@ void SurfaceFlinger::sample() { void SurfaceFlinger::onActiveDisplaySizeChanged(const DisplayDevice& activeDisplay) { mScheduler->onActiveDisplayAreaChanged(activeDisplay.getWidth() * activeDisplay.getHeight()); getRenderEngine().onActiveDisplaySizeChanged(activeDisplay.getSize()); + + // Notify layers to update small dirty flag. + if (mScheduler->supportSmallDirtyDetection()) { + mCurrentState.traverse([&](Layer* layer) { + if (layer->getLayerStack() == activeDisplay.getLayerStack()) { + layer->setIsSmallDirty(); + } + }); + } } sp SurfaceFlinger::getActivatableDisplay() const { diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 51b5b05bed..b67494fa23 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -1070,6 +1070,77 @@ TEST_F(LayerHistoryTest, heuristicLayerNotOscillating) { recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); } +TEST_F(LayerHistoryTest, smallDirtyLayer) { + auto layer = createLayer(); + + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + LayerHistory::Summary summary; + + // layer is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + auto props = layer->getLayerProps(); + if (i % 3 == 0) { + props.isSmallDirty = false; + } else { + props.isSmallDirty = true; + } + + history().record(layer->getSequence(), props, time, time, + LayerHistory::LayerUpdateType::Buffer); + time += HI_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_GE(HI_FPS, summary[0].desiredRefreshRate); +} + +TEST_F(LayerHistoryTest, smallDirtyInMultiLayer) { + auto layer1 = createLayer("UI"); + auto layer2 = createLayer("Video"); + + EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer1, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); + + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, getFrameRateForLayerTree()) + .WillRepeatedly( + Return(Layer::FrameRate(30_Hz, Layer::FrameRateCompatibility::Default))); + + nsecs_t time = systemTime(); + + EXPECT_EQ(2, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + LayerHistory::Summary summary; + + // layer1 is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + auto props = layer1->getLayerProps(); + props.isSmallDirty = true; + history().record(layer1->getSequence(), props, 0 /*presentTime*/, time, + LayerHistory::LayerUpdateType::Buffer); + history().record(layer2->getSequence(), layer2->getLayerProps(), time, time, + LayerHistory::LayerUpdateType::Buffer); + time += HI_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); + ASSERT_EQ(30_Hz, summary[0].desiredRefreshRate); +} + class LayerHistoryTestParameterized : public LayerHistoryTest, public testing::WithParamInterface { }; -- cgit v1.2.3-59-g8ed1b From 9ac5e6e6b2a9700268165c6556d30afe24fc204c Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Thu, 24 Aug 2023 09:01:44 +0000 Subject: VRR: Allowlist for small area detection Add a allowlist mechanism for suppress frame rate when small area. In this patch, we will keep a array list to record pkg name which want to apply the small area detection for suppressing frame rate and its threshold value of small area ratio. In framewokr, we will check the all pkg uid by pkg name from package manager and call a native function which include uid and threshold. In SF native, it get the threshold of uid and we will save them as a map, and it will used to check should it apply small area detection and what threshold it should use. Bug: 281720315 Test: atest SmallAreaDetectionMappingsTest Test: atest LayerHistoryTest Change-Id: Iaf6c0090f9db499fc5ed097b2d3c6d9d871d4812 --- libs/gui/SurfaceComposerClient.cpp | 14 +++++ libs/gui/aidl/android/gui/ISurfaceComposer.aidl | 9 ++++ libs/gui/fuzzer/libgui_fuzzer_utils.h | 3 ++ libs/gui/include/gui/SurfaceComposerClient.h | 10 ++++ libs/gui/tests/Surface_test.cpp | 9 ++++ services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 4 +- services/surfaceflinger/Scheduler/LayerHistory.h | 4 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 16 ++++++ services/surfaceflinger/Scheduler/Scheduler.h | 14 +++-- .../Scheduler/SmallAreaDetectionAllowMappings.cpp | 47 +++++++++++++++++ .../Scheduler/SmallAreaDetectionAllowMappings.h | 39 ++++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 45 ++++++++++++++++ services/surfaceflinger/SurfaceFlinger.h | 7 +++ services/surfaceflinger/tests/unittests/Android.bp | 1 + .../SmallAreaDetectionAllowMappingsTest.cpp | 61 ++++++++++++++++++++++ 17 files changed, 276 insertions(+), 11 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp create mode 100644 services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h create mode 100644 services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 92589c5742..4719e246e7 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2768,6 +2768,20 @@ status_t SurfaceComposerClient::setOverrideFrameRate(uid_t uid, float frameRate) return statusTFromBinderStatus(status); } +status_t SurfaceComposerClient::updateSmallAreaDetection(std::vector& uids, + std::vector& thresholds) { + binder::Status status = + ComposerServiceAIDL::getComposerService()->updateSmallAreaDetection(uids, thresholds); + return statusTFromBinderStatus(status); +} + +status_t SurfaceComposerClient::setSmallAreaDetectionThreshold(uid_t uid, float threshold) { + binder::Status status = + ComposerServiceAIDL::getComposerService()->setSmallAreaDetectionThreshold(uid, + threshold); + return statusTFromBinderStatus(status); +} + void SurfaceComposerClient::setAutoLowLatencyMode(const sp& display, bool on) { ComposerServiceAIDL::getComposerService()->setAutoLowLatencyMode(display, on); } diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index c2f47fc5ba..1c604a1f8b 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -479,6 +479,15 @@ interface ISurfaceComposer { */ void setOverrideFrameRate(int uid, float frameRate); + oneway void updateSmallAreaDetection(in int[] uids, in float[] thresholds); + + /** + * Set the small area detection threshold for a specified uid by SmallAreaDetectionController. + * Passing the threshold and uid to SurfaceFlinger to update the uid-threshold mapping + * in the scheduler. + */ + oneway void setSmallAreaDetectionThreshold(int uid, float threshold); + /** * Enables or disables the frame rate overlay in the top left corner. * Requires root or android.permission.HARDWARE_TEST diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h index 2643fa7d68..177d5f89c9 100644 --- a/libs/gui/fuzzer/libgui_fuzzer_utils.h +++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h @@ -154,6 +154,9 @@ public: MOCK_METHOD(binder::Status, setDebugFlash, (int), (override)); MOCK_METHOD(binder::Status, scheduleComposite, (), (override)); MOCK_METHOD(binder::Status, scheduleCommit, (), (override)); + MOCK_METHOD(binder::Status, updateSmallAreaDetection, + (const std::vector&, const std::vector&), (override)); + MOCK_METHOD(binder::Status, setSmallAreaDetectionThreshold, (int32_t, float), (override)); MOCK_METHOD(binder::Status, getGpuContextPriority, (int32_t*), (override)); MOCK_METHOD(binder::Status, getMaxAcquiredBufferCount, (int32_t*), (override)); MOCK_METHOD(binder::Status, addWindowInfosListener, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index fd9f186663..6fef5d2378 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -203,6 +203,16 @@ public: // by GameManager. static status_t setOverrideFrameRate(uid_t uid, float frameRate); + // Update the small area detection whole uid-threshold mappings by same size uid and threshold + // vector. + // Ref:setSmallAreaDetectionThreshold. + static status_t updateSmallAreaDetection(std::vector& uids, + std::vector& thresholds); + + // Sets the small area detection threshold to particular apps (uid). Passing value 0 means + // to disable small area detection to the app. + static status_t setSmallAreaDetectionThreshold(uid_t uid, float threshold); + // Switches on/off Auto Low Latency Mode on the connected display. This should only be // called if the connected display supports Auto Low Latency Mode as reported by // #getAutoLowLatencyModeSupport diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ffb8622f39..daed764cd6 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -999,6 +999,15 @@ public: binder::Status scheduleCommit() override { return binder::Status::ok(); } + binder::Status updateSmallAreaDetection(const std::vector& /*uids*/, + const std::vector& /*thresholds*/) { + return binder::Status::ok(); + } + + binder::Status setSmallAreaDetectionThreshold(int32_t /*uid*/, float /*threshold*/) { + return binder::Status::ok(); + } + binder::Status getGpuContextPriority(int32_t* /*outPriority*/) override { return binder::Status::ok(); } diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 0101c1712a..eda52bfcb5 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -187,6 +187,7 @@ filegroup { "Scheduler/MessageQueue.cpp", "Scheduler/RefreshRateSelector.cpp", "Scheduler/Scheduler.cpp", + "Scheduler/SmallAreaDetectionAllowMappings.cpp", "Scheduler/VSyncDispatchTimerQueue.cpp", "Scheduler/VSyncPredictor.cpp", "Scheduler/VSyncReactor.cpp", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8f785a044c..077ed674ad 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -4388,7 +4388,8 @@ void Layer::setIsSmallDirty() { // If the damage region is a small dirty, this could give the hint for the layer history that // it could suppress the heuristic rate when calculating. - mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(bounds.getWidth() * bounds.getHeight()); + mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerUid, + bounds.getWidth() * bounds.getHeight()); } } // namespace android diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 13cf764746..c92e670aa9 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -306,9 +306,9 @@ auto LayerHistory::findLayer(int32_t id) -> std::pair { return {LayerStatus::NotFound, nullptr}; } -bool LayerHistory::isSmallDirtyArea(uint32_t dirtyArea) const { +bool LayerHistory::isSmallDirtyArea(uint32_t dirtyArea, float threshold) const { const float ratio = (float)dirtyArea / mDisplayArea; - const bool isSmallDirty = ratio <= kSmallDirtyArea; + const bool isSmallDirty = ratio <= threshold; ATRACE_FORMAT_INSTANT("small dirty=%s, ratio=%.3f", isSmallDirty ? "true" : "false", ratio); return isSmallDirty; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 562bb4cace..5750ea7898 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -85,14 +85,12 @@ public: // return the frames per second of the layer with the given sequence id. float getLayerFramerate(nsecs_t now, int32_t id) const; - bool isSmallDirtyArea(uint32_t dirtyArea) const; + bool isSmallDirtyArea(uint32_t dirtyArea, float threshold) const; private: friend class LayerHistoryTest; friend class TestableScheduler; - static constexpr float kSmallDirtyArea = 0.07f; - using LayerPair = std::pair>; // keyed by id as returned from Layer::getSequence() using LayerInfos = std::unordered_map; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 5a19ec5095..27c96f7d4f 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -1179,4 +1179,20 @@ void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverrid mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride); } +void Scheduler::updateSmallAreaDetection( + std::vector>& uidThresholdMappings) { + mSmallAreaDetectionAllowMappings.update(uidThresholdMappings); +} + +void Scheduler::setSmallAreaDetectionThreshold(uid_t uid, float threshold) { + mSmallAreaDetectionAllowMappings.setThesholdForUid(uid, threshold); +} + +bool Scheduler::isSmallDirtyArea(uid_t uid, uint32_t dirtyArea) { + std::optional oThreshold = mSmallAreaDetectionAllowMappings.getThresholdForUid(uid); + if (oThreshold) return mLayerHistory.isSmallDirtyArea(dirtyArea, oThreshold.value()); + + return false; +} + } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index ec20610f81..d65df2a65d 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -49,6 +49,7 @@ #include "MessageQueue.h" #include "OneShotTimer.h" #include "RefreshRateSelector.h" +#include "SmallAreaDetectionAllowMappings.h" #include "Utils/Dumper.h" #include "VsyncModulator.h" @@ -291,6 +292,13 @@ public: void setGameModeRefreshRateForUid(FrameRateOverride); + void updateSmallAreaDetection(std::vector>& uidThresholdMappings); + + void setSmallAreaDetectionThreshold(uid_t uid, float threshold); + + // Returns true if the dirty area is less than threshold. + bool isSmallDirtyArea(uid_t uid, uint32_t dirtyArea); + // Retrieves the overridden refresh rate for a given uid. std::optional getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock); @@ -314,11 +322,6 @@ public: return mFeatures.test(Feature::kSmallDirtyContentDetection); } - // Returns true if the dirty area is less than threshold. - bool isSmallDirtyArea(uint32_t dirtyArea) const { - return mLayerHistory.isSmallDirtyArea(dirtyArea); - } - private: friend class TestableScheduler; @@ -557,6 +560,7 @@ private: static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; FrameRateOverrideMappings mFrameRateOverrideMappings; + SmallAreaDetectionAllowMappings mSmallAreaDetectionAllowMappings; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp new file mode 100644 index 0000000000..95cd5d199a --- /dev/null +++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp @@ -0,0 +1,47 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include "SmallAreaDetectionAllowMappings.h" + +namespace android::scheduler { +void SmallAreaDetectionAllowMappings::update( + std::vector>& uidThresholdMappings) { + std::lock_guard lock(mLock); + mMap.clear(); + for (std::pair row : uidThresholdMappings) { + if (!isValidThreshold(row.second)) continue; + + mMap.emplace(row.first, row.second); + } +} + +void SmallAreaDetectionAllowMappings::setThesholdForUid(uid_t uid, float threshold) { + if (!isValidThreshold(threshold)) return; + + std::lock_guard lock(mLock); + mMap.emplace(uid, threshold); +} + +std::optional SmallAreaDetectionAllowMappings::getThresholdForUid(uid_t uid) { + std::lock_guard lock(mLock); + const auto iter = mMap.find(uid); + if (iter != mMap.end()) { + return iter->second; + } + return std::nullopt; +} +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h new file mode 100644 index 0000000000..cbab69091f --- /dev/null +++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace android::scheduler { +class SmallAreaDetectionAllowMappings { + using UidThresholdMap = std::unordered_map; + +public: + void update(std::vector>& uidThresholdMappings); + void setThesholdForUid(uid_t uid, float threshold) EXCLUDES(mLock); + std::optional getThresholdForUid(uid_t uid) EXCLUDES(mLock); + +private: + static bool isValidThreshold(float threshold) { return threshold >= 0.0f && threshold <= 1.0f; } + mutable std::mutex mLock; + UidThresholdMap mMap GUARDED_BY(mLock); +}; +} // namespace android::scheduler diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 940a4c6b66..bc626f3030 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -8200,6 +8200,17 @@ status_t SurfaceFlinger::setOverrideFrameRate(uid_t uid, float frameRate) { return NO_ERROR; } +status_t SurfaceFlinger::updateSmallAreaDetection( + std::vector>& uidThresholdMappings) { + mScheduler->updateSmallAreaDetection(uidThresholdMappings); + return NO_ERROR; +} + +status_t SurfaceFlinger::setSmallAreaDetectionThreshold(uid_t uid, float threshold) { + mScheduler->setSmallAreaDetectionThreshold(uid, threshold); + return NO_ERROR; +} + void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { bool setByHwc = getHwComposer().hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG); for (const auto& [id, display] : mPhysicalDisplays) { @@ -9532,6 +9543,40 @@ binder::Status SurfaceComposerAIDL::scheduleCommit() { return binder::Status::ok(); } +binder::Status SurfaceComposerAIDL::updateSmallAreaDetection(const std::vector& uids, + const std::vector& thresholds) { + status_t status; + const int c_uid = IPCThreadState::self()->getCallingUid(); + if (c_uid == AID_ROOT || c_uid == AID_SYSTEM) { + if (uids.size() != thresholds.size()) return binderStatusFromStatusT(BAD_VALUE); + + std::vector> mappings; + const size_t size = uids.size(); + mappings.reserve(size); + for (int i = 0; i < size; i++) { + auto row = std::make_pair(static_cast(uids[i]), thresholds[i]); + mappings.push_back(row); + } + status = mFlinger->updateSmallAreaDetection(mappings); + } else { + ALOGE("updateSmallAreaDetection() permission denied for uid: %d", c_uid); + status = PERMISSION_DENIED; + } + return binderStatusFromStatusT(status); +} + +binder::Status SurfaceComposerAIDL::setSmallAreaDetectionThreshold(int32_t uid, float threshold) { + status_t status; + const int c_uid = IPCThreadState::self()->getCallingUid(); + if (c_uid == AID_ROOT || c_uid == AID_SYSTEM) { + status = mFlinger->setSmallAreaDetectionThreshold(uid, threshold); + } else { + ALOGE("setSmallAreaDetectionThreshold() permission denied for uid: %d", c_uid); + status = PERMISSION_DENIED; + } + return binderStatusFromStatusT(status); +} + binder::Status SurfaceComposerAIDL::getGpuContextPriority(int32_t* outPriority) { *outPriority = mFlinger->getGpuContextPriority(); return binder::Status::ok(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6ff9fd1111..79dcd0d1b2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -607,6 +607,10 @@ private: status_t setOverrideFrameRate(uid_t uid, float frameRate); + status_t updateSmallAreaDetection(std::vector>& uidThresholdMappings); + + status_t setSmallAreaDetectionThreshold(uid_t uid, float threshold); + int getGpuContextPriority(); status_t getMaxAcquiredBufferCount(int* buffers) const; @@ -1557,6 +1561,9 @@ public: binder::Status setDebugFlash(int delay) override; binder::Status scheduleComposite() override; binder::Status scheduleCommit() override; + binder::Status updateSmallAreaDetection(const std::vector& uids, + const std::vector& thresholds) override; + binder::Status setSmallAreaDetectionThreshold(int32_t uid, float threshold) override; binder::Status getGpuContextPriority(int32_t* outPriority) override; binder::Status getMaxAcquiredBufferCount(int32_t* buffers) override; binder::Status addWindowInfosListener(const sp& windowInfosListener, diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 7d8796f71c..8deff85118 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -101,6 +101,7 @@ cc_test { "LayerTestUtils.cpp", "MessageQueueTest.cpp", "PowerAdvisorTest.cpp", + "SmallAreaDetectionAllowMappingsTest.cpp", "SurfaceFlinger_CreateDisplayTest.cpp", "SurfaceFlinger_DestroyDisplayTest.cpp", "SurfaceFlinger_DisplayModeSwitching.cpp", diff --git a/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp b/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp new file mode 100644 index 0000000000..b910485c06 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "SmallAreaDetectionAllowMappingsTest" + +#include + +#include "Scheduler/SmallAreaDetectionAllowMappings.h" + +namespace android::scheduler { + +class SmallAreaDetectionMappingsAllowTest : public testing::Test { +protected: + SmallAreaDetectionAllowMappings mMappings; +}; + +namespace { +TEST_F(SmallAreaDetectionMappingsAllowTest, testUpdate) { + const uid_t uid1 = 10100; + const uid_t uid2 = 10101; + const float threshold1 = 0.05f; + const float threshold2 = 0.07f; + std::vector> mappings; + mappings.reserve(2); + mappings.push_back(std::make_pair(uid1, threshold1)); + mappings.push_back(std::make_pair(uid2, threshold2)); + + mMappings.update(mappings); + ASSERT_EQ(mMappings.getThresholdForUid(uid1).value(), threshold1); + ASSERT_EQ(mMappings.getThresholdForUid(uid2).value(), threshold2); +} + +TEST_F(SmallAreaDetectionMappingsAllowTest, testSetThesholdForUid) { + const uid_t uid = 10111; + const float threshold = 0.05f; + + mMappings.setThesholdForUid(uid, threshold); + ASSERT_EQ(mMappings.getThresholdForUid(uid), threshold); +} + +TEST_F(SmallAreaDetectionMappingsAllowTest, testUidNotInTheMappings) { + const uid_t uid = 10222; + ASSERT_EQ(mMappings.getThresholdForUid(uid), std::nullopt); +} + +} // namespace +} // namespace android::scheduler -- cgit v1.2.3-59-g8ed1b From 7c1d8b5b207169d36c4b26bcf70f4923569afe43 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 29 Aug 2023 20:14:46 +0000 Subject: Use the correct frame rate vote for metrics Applications using preferredDisplayModeId to request a frame rate will have their vote recorded on the task SurfaceControl, so the entire layer tree vote needs to be used. Bug: 284866750 Test: builds Test: test app setting preferredDisplayModeId Change-Id: I04c575e58b842bebf5f79d86ec7ab7e738079886 --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index af4b65bcbc..93ebc8cc93 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -4018,7 +4018,7 @@ void Layer::onPostComposition(const DisplayDevice* display, const std::optional renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); - const auto vote = frameRateToSetFrameRateVotePayload(mDrawingState.frameRate); + const auto vote = frameRateToSetFrameRateVotePayload(getFrameRateForLayerTree()); const auto gameMode = getGameMode(); if (presentFence->isValid()) { -- cgit v1.2.3-59-g8ed1b From b194d7ba3c207505c5eeafa407e3c3e256461da2 Mon Sep 17 00:00:00 2001 From: Diwas Sharma Date: Fri, 1 Sep 2023 00:43:15 +0000 Subject: Revert "Revert layer proto format back to proto2" This reverts commit 5dad909092932dc5c02d1be2f6ece1a3d06908ad. Reason for revert: 298512106 Change-Id: I6c371f9958b2112f51ba801131ee912dff5a4da7 --- services/surfaceflinger/Layer.cpp | 4 ++++ services/surfaceflinger/layerproto/LayerProtoParser.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9a5173ba9b..d4babdbd79 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2325,11 +2325,15 @@ void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote(); if (parent != nullptr) { layerInfo->set_parent(parent->sequence); + } else { + layerInfo->set_parent(-1); } auto zOrderRelativeOf = state.zOrderRelativeOf.promote(); if (zOrderRelativeOf != nullptr) { layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); + } else { + layerInfo->set_z_order_relative_of(-1); } layerInfo->set_is_relative_of(state.isRelativeOf); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index c3d0a40261..8d48070e13 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -193,13 +193,13 @@ void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerPr } } - if (layerProto.has_parent()) { + if (layerProto.parent() != -1) { if (layerMap.count(layerProto.parent()) > 0) { currLayer->parent = layerMap[layerProto.parent()]; } } - if (layerProto.has_z_order_relative_of()) { + if (layerProto.z_order_relative_of() != -1) { if (layerMap.count(layerProto.z_order_relative_of()) > 0) { currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()]; } -- cgit v1.2.3-59-g8ed1b From 2401daf78395903f1940bbb1b5e2bc777efd2802 Mon Sep 17 00:00:00 2001 From: Diwas Sharma Date: Fri, 1 Sep 2023 00:45:24 +0000 Subject: Revert "Move proto definitions to external/perfetto" This reverts commit bec51fdc3c8a42cbcb833d7d14800fbb0a14a7f3. Reason for revert: 298512106 Change-Id: Icb9d6d5a23176a809c3b71bcaa3928b03dfb0622 --- services/surfaceflinger/Layer.cpp | 26 +- services/surfaceflinger/Layer.h | 12 +- services/surfaceflinger/LayerProtoHelper.cpp | 83 +++--- services/surfaceflinger/LayerProtoHelper.h | 62 ++--- services/surfaceflinger/SurfaceFlinger.cpp | 29 +- services/surfaceflinger/SurfaceFlinger.h | 10 +- .../Tracing/TransactionProtoParser.cpp | 82 +++--- .../Tracing/TransactionProtoParser.h | 28 +- .../surfaceflinger/Tracing/TransactionTracing.cpp | 39 ++- .../surfaceflinger/Tracing/TransactionTracing.h | 22 +- .../Tracing/tools/LayerTraceGenerator.cpp | 4 +- .../Tracing/tools/LayerTraceGenerator.h | 4 +- services/surfaceflinger/Tracing/tools/main.cpp | 2 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 3 +- services/surfaceflinger/layerproto/Android.bp | 38 ++- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 25 +- services/surfaceflinger/layerproto/common.proto | 92 ++++++ services/surfaceflinger/layerproto/display.proto | 42 +++ .../include/layerproto/LayerProtoHeader.h | 7 +- .../include/layerproto/LayerProtoParser.h | 21 +- .../include/layerproto/TransactionProto.h | 6 +- .../surfaceflinger/layerproto/jarjar-rules.txt | 1 + services/surfaceflinger/layerproto/layers.proto | 171 ++++++++++++ .../surfaceflinger/layerproto/layerstrace.proto | 69 +++++ .../surfaceflinger/layerproto/transactions.proto | 310 +++++++++++++++++++++ services/surfaceflinger/tests/Stress_test.cpp | 8 +- .../tests/tracing/TransactionTraceTestSuite.cpp | 4 +- .../tests/unittests/TransactionProtoParserTest.cpp | 4 +- .../tests/unittests/TransactionTracingTest.cpp | 26 +- 29 files changed, 934 insertions(+), 296 deletions(-) create mode 100644 services/surfaceflinger/layerproto/common.proto create mode 100644 services/surfaceflinger/layerproto/display.proto create mode 100644 services/surfaceflinger/layerproto/jarjar-rules.txt create mode 100644 services/surfaceflinger/layerproto/layers.proto create mode 100644 services/surfaceflinger/layerproto/layerstrace.proto create mode 100644 services/surfaceflinger/layerproto/transactions.proto (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d4babdbd79..cdf7cff76d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -139,7 +139,7 @@ using gui::WindowInfo; using PresentState = frametimeline::SurfaceFrame::PresentState; -Layer::Layer(const surfaceflinger::LayerCreationArgs& args) +Layer::Layer(const LayerCreationArgs& args) : sequence(args.sequence), mFlinger(sp::fromExisting(args.flinger)), mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)), @@ -1000,8 +1000,8 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; std::string name = mName + "BackgroundColorLayer"; mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer( - surfaceflinger::LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, - LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, + LayerMetadata())); // add to child list addChild(mDrawingState.bgColorLayer); @@ -2203,9 +2203,8 @@ void Layer::setInputInfo(const WindowInfo& info) { setTransactionFlags(eTransactionNeeded); } -perfetto::protos::LayerProto* Layer::writeToProto(perfetto::protos::LayersProto& layersProto, - uint32_t traceFlags) { - perfetto::protos::LayerProto* layerProto = layersProto.add_layers(); +LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { + LayerProto* layerProto = layersProto.add_layers(); writeToProtoDrawingState(layerProto); writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); @@ -2222,22 +2221,20 @@ perfetto::protos::LayerProto* Layer::writeToProto(perfetto::protos::LayersProto& return layerProto; } -void Layer::writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto, - ui::LayerStack layerStack) { +void Layer::writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack) { ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread. ftl::FakeGuard mainThreadGuard(kMainThreadContext); // Only populate for the primary display. if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) { const auto compositionType = getCompositionType(*display); - layerProto->set_hwc_composition_type( - static_cast(compositionType)); + layerProto->set_hwc_composition_type(static_cast(compositionType)); LayerProtoHelper::writeToProto(getVisibleRegion(display), [&]() { return layerProto->mutable_visible_region(); }); } } -void Layer::writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo) { +void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { const ui::Transform transform = getTransform(); auto buffer = getExternalTexture(); if (buffer != nullptr) { @@ -2276,8 +2273,8 @@ void Layer::writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo) { layerInfo->set_shadow_radius(mEffectiveShadowRadius); } -void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, - LayerVector::StateSet stateSet, uint32_t traceFlags) { +void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, + uint32_t traceFlags) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mDrawingState; @@ -3633,8 +3630,7 @@ Rect Layer::computeBufferCrop(const State& s) { } sp Layer::createClone(uint32_t mirrorRootId) { - surfaceflinger::LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, - LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()); sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->setInitialValuesForClone(sp::fromExisting(this), mirrorRootId); return layer; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index dc4ceb0bfa..7b6c56b6a8 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -235,7 +235,7 @@ public: bool useVsyncIdForRefreshRateSelection = false; }; - explicit Layer(const surfaceflinger::LayerCreationArgs& args); + explicit Layer(const LayerCreationArgs& args); virtual ~Layer(); static bool isLayerFocusedBasedOnPriority(int32_t priority); @@ -634,19 +634,17 @@ public: bool isRemovedFromCurrentState() const; - perfetto::protos::LayerProto* writeToProto(perfetto::protos::LayersProto& layersProto, - uint32_t traceFlags); - void writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto, - ui::LayerStack layerStack); + LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags); + void writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack); // Write states that are modified by the main thread. This includes drawing // state as well as buffer data. This should be called in the main or tracing // thread. - void writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo); + void writeToProtoDrawingState(LayerProto* layerInfo); // Write drawing or current state. If writing current state, the caller should hold the // external mStateLock. If writing drawing state, this function should be called on the // main or tracing thread. - void writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, LayerVector::StateSet, + void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet, uint32_t traceFlags = LayerTracing::TRACE_ALL); gui::WindowInfo::Type getWindowType() const { return mWindowType; } diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 144e1f5abf..341f041086 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -29,30 +29,28 @@ using gui::WindowInfo; namespace surfaceflinger { -void LayerProtoHelper::writePositionToProto( - const float x, const float y, - std::function getPositionProto) { +void LayerProtoHelper::writePositionToProto(const float x, const float y, + std::function getPositionProto) { if (x != 0 || y != 0) { // Use a lambda do avoid writing the object header when the object is empty - perfetto::protos::PositionProto* position = getPositionProto(); + PositionProto* position = getPositionProto(); position->set_x(x); position->set_y(y); } } -void LayerProtoHelper::writeSizeToProto( - const uint32_t w, const uint32_t h, - std::function getSizeProto) { +void LayerProtoHelper::writeSizeToProto(const uint32_t w, const uint32_t h, + std::function getSizeProto) { if (w != 0 || h != 0) { // Use a lambda do avoid writing the object header when the object is empty - perfetto::protos::SizeProto* size = getSizeProto(); + SizeProto* size = getSizeProto(); size->set_w(w); size->set_h(h); } } -void LayerProtoHelper::writeToProto( - const Region& region, std::function getRegionProto) { +void LayerProtoHelper::writeToProto(const Region& region, + std::function getRegionProto) { if (region.isEmpty()) { return; } @@ -60,8 +58,7 @@ void LayerProtoHelper::writeToProto( writeToProto(region, getRegionProto()); } -void LayerProtoHelper::writeToProto(const Region& region, - perfetto::protos::RegionProto* regionProto) { +void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) { if (region.isEmpty()) { return; } @@ -75,8 +72,7 @@ void LayerProtoHelper::writeToProto(const Region& region, } } -void LayerProtoHelper::readFromProto(const perfetto::protos::RegionProto& regionProto, - Region& outRegion) { +void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& outRegion) { for (int i = 0; i < regionProto.rect_size(); i++) { Rect rect; readFromProto(regionProto.rect(i), rect); @@ -84,34 +80,32 @@ void LayerProtoHelper::readFromProto(const perfetto::protos::RegionProto& region } } -void LayerProtoHelper::writeToProto(const Rect& rect, - std::function getRectProto) { +void LayerProtoHelper::writeToProto(const Rect& rect, std::function getRectProto) { if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) { // Use a lambda do avoid writing the object header when the object is empty writeToProto(rect, getRectProto()); } } -void LayerProtoHelper::writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto) { +void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { rectProto->set_left(rect.left); rectProto->set_top(rect.top); rectProto->set_bottom(rect.bottom); rectProto->set_right(rect.right); } -void LayerProtoHelper::readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect) { +void LayerProtoHelper::readFromProto(const RectProto& proto, Rect& outRect) { outRect.left = proto.left(); outRect.top = proto.top(); outRect.bottom = proto.bottom(); outRect.right = proto.right(); } -void LayerProtoHelper::writeToProto( - const FloatRect& rect, - std::function getFloatRectProto) { +void LayerProtoHelper::writeToProto(const FloatRect& rect, + std::function getFloatRectProto) { if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) { // Use a lambda do avoid writing the object header when the object is empty - perfetto::protos::FloatRectProto* rectProto = getFloatRectProto(); + FloatRectProto* rectProto = getFloatRectProto(); rectProto->set_left(rect.left); rectProto->set_top(rect.top); rectProto->set_bottom(rect.bottom); @@ -119,11 +113,10 @@ void LayerProtoHelper::writeToProto( } } -void LayerProtoHelper::writeToProto(const half4 color, - std::function getColorProto) { +void LayerProtoHelper::writeToProto(const half4 color, std::function getColorProto) { if (color.r != 0 || color.g != 0 || color.b != 0 || color.a != 0) { // Use a lambda do avoid writing the object header when the object is empty - perfetto::protos::ColorProto* colorProto = getColorProto(); + ColorProto* colorProto = getColorProto(); colorProto->set_r(color.r); colorProto->set_g(color.g); colorProto->set_b(color.b); @@ -132,7 +125,7 @@ void LayerProtoHelper::writeToProto(const half4 color, } void LayerProtoHelper::writeToProtoDeprecated(const ui::Transform& transform, - perfetto::protos::TransformProto* transformProto) { + TransformProto* transformProto) { const uint32_t type = transform.getType() | (transform.getOrientation() << 8); transformProto->set_type(type); @@ -148,7 +141,7 @@ void LayerProtoHelper::writeToProtoDeprecated(const ui::Transform& transform, } void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform, - perfetto::protos::TransformProto* transformProto) { + TransformProto* transformProto) { const uint32_t type = transform.getType() | (transform.getOrientation() << 8); transformProto->set_type(type); @@ -163,13 +156,12 @@ void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform, } } -void LayerProtoHelper::writeToProto( - const renderengine::ExternalTexture& buffer, - std::function getActiveBufferProto) { +void LayerProtoHelper::writeToProto(const renderengine::ExternalTexture& buffer, + std::function getActiveBufferProto) { if (buffer.getWidth() != 0 || buffer.getHeight() != 0 || buffer.getUsage() != 0 || buffer.getPixelFormat() != 0) { // Use a lambda do avoid writing the object header when the object is empty - auto* activeBufferProto = getActiveBufferProto(); + ActiveBufferProto* activeBufferProto = getActiveBufferProto(); activeBufferProto->set_width(buffer.getWidth()); activeBufferProto->set_height(buffer.getHeight()); activeBufferProto->set_stride(buffer.getUsage()); @@ -179,12 +171,12 @@ void LayerProtoHelper::writeToProto( void LayerProtoHelper::writeToProto( const WindowInfo& inputInfo, const wp& touchableRegionBounds, - std::function getInputWindowInfoProto) { + std::function getInputWindowInfoProto) { if (inputInfo.token == nullptr) { return; } - perfetto::protos::InputWindowInfoProto* proto = getInputWindowInfoProto(); + InputWindowInfoProto* proto = getInputWindowInfoProto(); proto->set_layout_params_flags(inputInfo.layoutParamsFlags.get()); proto->set_input_config(inputInfo.inputConfig.get()); using U = std::underlying_type_t; @@ -217,8 +209,7 @@ void LayerProtoHelper::writeToProto( } } -void LayerProtoHelper::writeToProto(const mat4 matrix, - perfetto::protos::ColorTransformProto* colorTransformProto) { +void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto) { for (int i = 0; i < mat4::ROW_SIZE; i++) { for (int j = 0; j < mat4::COL_SIZE; j++) { colorTransformProto->add_val(matrix[i][j]); @@ -226,8 +217,7 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, } } -void LayerProtoHelper::readFromProto( - const perfetto::protos::ColorTransformProto& colorTransformProto, mat4& matrix) { +void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix) { for (int i = 0; i < mat4::ROW_SIZE; i++) { for (int j = 0; j < mat4::COL_SIZE; j++) { matrix[i][j] = colorTransformProto.val(i * mat4::COL_SIZE + j); @@ -235,8 +225,7 @@ void LayerProtoHelper::readFromProto( } } -void LayerProtoHelper::writeToProto(const android::BlurRegion region, - perfetto::protos::BlurRegion* proto) { +void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion* proto) { proto->set_blur_radius(region.blurRadius); proto->set_corner_radius_tl(region.cornerRadiusTL); proto->set_corner_radius_tr(region.cornerRadiusTR); @@ -249,8 +238,7 @@ void LayerProtoHelper::writeToProto(const android::BlurRegion region, proto->set_bottom(region.bottom); } -void LayerProtoHelper::readFromProto(const perfetto::protos::BlurRegion& proto, - android::BlurRegion& outRegion) { +void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion) { outRegion.blurRadius = proto.blur_radius(); outRegion.cornerRadiusTL = proto.corner_radius_tl(); outRegion.cornerRadiusTR = proto.corner_radius_tr(); @@ -263,8 +251,7 @@ void LayerProtoHelper::readFromProto(const perfetto::protos::BlurRegion& proto, outRegion.bottom = proto.bottom(); } -perfetto::protos::LayersProto LayerProtoFromSnapshotGenerator::generate( - const frontend::LayerHierarchy& root) { +LayersProto LayerProtoFromSnapshotGenerator::generate(const frontend::LayerHierarchy& root) { mLayersProto.clear_layers(); std::unordered_set stackIdsToSkip; if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) { @@ -323,7 +310,7 @@ frontend::LayerSnapshot* LayerProtoFromSnapshotGenerator::getSnapshot( void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( const frontend::LayerHierarchy& root, frontend::LayerHierarchy::TraversalPath& path) { using Variant = frontend::LayerHierarchy::Variant; - perfetto::protos::LayerProto* layerProto = mLayersProto.add_layers(); + LayerProto* layerProto = mLayersProto.add_layers(); const frontend::RequestedLayerState& layer = *root.getLayer(); frontend::LayerSnapshot* snapshot = getSnapshot(path, layer); LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags); @@ -362,7 +349,7 @@ void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( } } -void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerInfo, +void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags) { @@ -459,9 +446,9 @@ void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerI [&]() { return layerInfo->mutable_destination_frame(); }); } -google::protobuf::RepeatedPtrField -LayerProtoHelper::writeDisplayInfoToProto(const frontend::DisplayInfos& displayInfos) { - google::protobuf::RepeatedPtrField displays; +google::protobuf::RepeatedPtrField LayerProtoHelper::writeDisplayInfoToProto( + const frontend::DisplayInfos& displayInfos) { + google::protobuf::RepeatedPtrField displays; displays.Reserve(displayInfos.size()); for (const auto& [layerStack, displayInfo] : displayInfos) { auto displayProto = displays.Add(); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 20c226006c..346685f259 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -35,47 +35,39 @@ namespace android { namespace surfaceflinger { class LayerProtoHelper { public: - static void writePositionToProto( - const float x, const float y, - std::function getPositionProto); + static void writePositionToProto(const float x, const float y, + std::function getPositionProto); static void writeSizeToProto(const uint32_t w, const uint32_t h, - std::function getSizeProto); - static void writeToProto(const Rect& rect, - std::function getRectProto); - static void writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto); - static void readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect); + std::function getSizeProto); + static void writeToProto(const Rect& rect, std::function getRectProto); + static void writeToProto(const Rect& rect, RectProto* rectProto); + static void readFromProto(const RectProto& proto, Rect& outRect); static void writeToProto(const FloatRect& rect, - std::function getFloatRectProto); - static void writeToProto(const Region& region, - std::function getRegionProto); - static void writeToProto(const Region& region, perfetto::protos::RegionProto* regionProto); - static void readFromProto(const perfetto::protos::RegionProto& regionProto, Region& outRegion); - static void writeToProto(const half4 color, - std::function getColorProto); + std::function getFloatRectProto); + static void writeToProto(const Region& region, std::function getRegionProto); + static void writeToProto(const Region& region, RegionProto* regionProto); + static void readFromProto(const RegionProto& regionProto, Region& outRegion); + static void writeToProto(const half4 color, std::function getColorProto); // This writeToProto for transform is incorrect, but due to backwards compatibility, we can't // update Layers to use it. Use writeTransformToProto for any new transform proto data. static void writeToProtoDeprecated(const ui::Transform& transform, - perfetto::protos::TransformProto* transformProto); + TransformProto* transformProto); static void writeTransformToProto(const ui::Transform& transform, - perfetto::protos::TransformProto* transformProto); - static void writeToProto( - const renderengine::ExternalTexture& buffer, - std::function getActiveBufferProto); - static void writeToProto( - const gui::WindowInfo& inputInfo, const wp& touchableRegionBounds, - std::function getInputWindowInfoProto); - static void writeToProto(const mat4 matrix, - perfetto::protos::ColorTransformProto* colorTransformProto); - static void readFromProto(const perfetto::protos::ColorTransformProto& colorTransformProto, - mat4& matrix); - static void writeToProto(const android::BlurRegion region, perfetto::protos::BlurRegion*); - static void readFromProto(const perfetto::protos::BlurRegion& proto, - android::BlurRegion& outRegion); - static void writeSnapshotToProto(perfetto::protos::LayerProto* outProto, + TransformProto* transformProto); + static void writeToProto(const renderengine::ExternalTexture& buffer, + std::function getActiveBufferProto); + static void writeToProto(const gui::WindowInfo& inputInfo, + const wp& touchableRegionBounds, + std::function getInputWindowInfoProto); + static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto); + static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix); + static void writeToProto(const android::BlurRegion region, BlurRegion*); + static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion); + static void writeSnapshotToProto(LayerProto* outProto, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags); - static google::protobuf::RepeatedPtrField - writeDisplayInfoToProto(const frontend::DisplayInfos&); + static google::protobuf::RepeatedPtrField writeDisplayInfoToProto( + const frontend::DisplayInfos&); }; class LayerProtoFromSnapshotGenerator { @@ -88,7 +80,7 @@ public: mLegacyLayers(legacyLayers), mDisplayInfos(displayInfos), mTraceFlags(traceFlags) {} - perfetto::protos::LayersProto generate(const frontend::LayerHierarchy& root); + LayersProto generate(const frontend::LayerHierarchy& root); private: void writeHierarchyToProto(const frontend::LayerHierarchy& root, @@ -100,7 +92,7 @@ private: const std::unordered_map>& mLegacyLayers; const frontend::DisplayInfos& mDisplayInfos; uint32_t mTraceFlags; - perfetto::protos::LayersProto mLayersProto; + LayersProto mLayersProto; // winscope expects all the layers, so provide a snapshot even if it not currently drawing std::unordered_map diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e24c0dba4d..bc626f3030 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5889,10 +5889,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { } if (dumpLayers) { - perfetto::protos::LayersTraceFileProto traceFileProto = - mLayerTracing.createTraceFileProto(); - perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); - perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread(); + LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto(); + LayersTraceProto* layersTrace = traceFileProto.add_entry(); + LayersProto layersProto = dumpProtoFromMainThread(); layersTrace->mutable_layers()->Swap(&layersProto); auto displayProtos = dumpDisplayProto(); layersTrace->mutable_displays()->Swap(&displayProtos); @@ -6118,7 +6117,7 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } -perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { +LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { std::unordered_set stackIdsToSkip; // Determine if virtual layers display should be skipped @@ -6131,7 +6130,7 @@ perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t tra } if (mLegacyFrontEndEnabled) { - perfetto::protos::LayersProto layersProto; + LayersProto layersProto; for (const sp& layer : mDrawingState.layersSortedByZ) { if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { continue; @@ -6146,11 +6145,10 @@ perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t tra .generate(mLayerHierarchyBuilder.getHierarchy()); } -google::protobuf::RepeatedPtrField -SurfaceFlinger::dumpDisplayProto() const { - google::protobuf::RepeatedPtrField displays; +google::protobuf::RepeatedPtrField SurfaceFlinger::dumpDisplayProto() const { + google::protobuf::RepeatedPtrField displays; for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { - perfetto::protos::DisplayProto* displayProto = displays.Add(); + DisplayProto* displayProto = displays.Add(); displayProto->set_id(display->getId().value); displayProto->set_name(display->getDisplayName()); displayProto->set_layer_stack(display->getLayerStack().id); @@ -6177,11 +6175,10 @@ void SurfaceFlinger::dumpHwc(std::string& result) const { getHwComposer().dump(result); } -void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, - uint32_t traceFlags) const { +void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const { // Add a fake invisible root layer to the proto output and parent all the offscreen layers to // it. - perfetto::protos::LayerProto* rootProto = layersProto.add_layers(); + LayerProto* rootProto = layersProto.add_layers(); const int32_t offscreenRootLayerId = INT32_MAX - 2; rootProto->set_id(offscreenRootLayerId); rootProto->set_name("Offscreen Root"); @@ -6192,12 +6189,12 @@ void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& lay rootProto->add_children(offscreenLayer->sequence); // Add layer - auto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); + LayerProto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); layerProto->set_parent(offscreenRootLayerId); } } -perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { +LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { return mScheduler->schedule([=] { return dumpDrawingStateProto(traceFlags); }).get(); } @@ -8793,7 +8790,7 @@ frontend::Update SurfaceFlinger::flushLifecycleUpdates() { void SurfaceFlinger::addToLayerTracing(bool visibleRegionDirty, TimePoint time, VsyncId vsyncId) { const uint32_t tracingFlags = mLayerTracing.getFlags(); - perfetto::protos::LayersProto layers(dumpDrawingStateProto(tracingFlags)); + LayersProto layers(dumpDrawingStateProto(tracingFlags)); if (tracingFlags & LayerTracing::TRACE_EXTRA) { dumpOffscreenLayersProto(layers); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 693bf3b35a..79dcd0d1b2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1092,17 +1092,17 @@ private: void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); - perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; - void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, + LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; + void dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags = LayerTracing::TRACE_ALL) const; - google::protobuf::RepeatedPtrField dumpDisplayProto() const; + google::protobuf::RepeatedPtrField dumpDisplayProto() const; void addToLayerTracing(bool visibleRegionDirty, TimePoint, VsyncId) REQUIRES(kMainThreadContext); // Dumps state from HW Composer void dumpHwc(std::string& result) const; - perfetto::protos::LayersProto dumpProtoFromMainThread( - uint32_t traceFlags = LayerTracing::TRACE_ALL) EXCLUDES(mStateLock); + LayersProto dumpProtoFromMainThread(uint32_t traceFlags = LayerTracing::TRACE_ALL) + EXCLUDES(mStateLock); void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock); void dumpPlannerInfo(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index 2dc89b55ba..b1e3d6378a 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -51,8 +51,8 @@ public: ~FakeExternalTexture() = default; }; -perfetto::protos::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { - perfetto::protos::TransactionState proto; +proto::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { + proto::TransactionState proto; proto.set_pid(t.originPid); proto.set_uid(t.originUid); proto.set_vsync_id(t.frameTimelineInfo.vsyncId); @@ -79,21 +79,21 @@ perfetto::protos::TransactionState TransactionProtoParser::toProto(const Transac return proto; } -perfetto::protos::TransactionState TransactionProtoParser::toProto( +proto::TransactionState TransactionProtoParser::toProto( const std::map& states) { - perfetto::protos::TransactionState proto; + proto::TransactionState proto; proto.mutable_layer_changes()->Reserve(static_cast(states.size())); for (auto& [layerId, state] : states) { - perfetto::protos::LayerState layerProto = toProto(state); + proto::LayerState layerProto = toProto(state); layerProto.set_has_sideband_stream(state.hasSidebandStream); proto.mutable_layer_changes()->Add(std::move(layerProto)); } return proto; } -perfetto::protos::LayerState TransactionProtoParser::toProto( +proto::LayerState TransactionProtoParser::toProto( const ResolvedComposerState& resolvedComposerState) { - perfetto::protos::LayerState proto; + proto::LayerState proto; auto& layer = resolvedComposerState.state; proto.set_layer_id(resolvedComposerState.layerId); proto.set_what(layer.what); @@ -114,7 +114,7 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( proto.set_mask(layer.mask); } if (layer.what & layer_state_t::eMatrixChanged) { - perfetto::protos::LayerState_Matrix22* matrixProto = proto.mutable_matrix(); + proto::LayerState_Matrix22* matrixProto = proto.mutable_matrix(); matrixProto->set_dsdx(layer.matrix.dsdx); matrixProto->set_dsdy(layer.matrix.dsdy); matrixProto->set_dtdx(layer.matrix.dtdx); @@ -132,7 +132,7 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eColorChanged) { - perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color(); + proto::LayerState_Color3* colorProto = proto.mutable_color(); colorProto->set_r(layer.color.r); colorProto->set_g(layer.color.g); colorProto->set_b(layer.color.b); @@ -150,14 +150,13 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( LayerProtoHelper::writeToProto(layer.crop, proto.mutable_crop()); } if (layer.what & layer_state_t::eBufferChanged) { - perfetto::protos::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); + proto::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); if (resolvedComposerState.externalTexture) { bufferProto->set_buffer_id(resolvedComposerState.externalTexture->getId()); bufferProto->set_width(resolvedComposerState.externalTexture->getWidth()); bufferProto->set_height(resolvedComposerState.externalTexture->getHeight()); - bufferProto->set_pixel_format( - static_cast( - resolvedComposerState.externalTexture->getPixelFormat())); + bufferProto->set_pixel_format(static_cast( + resolvedComposerState.externalTexture->getPixelFormat())); bufferProto->set_usage(resolvedComposerState.externalTexture->getUsage()); } bufferProto->set_frame_number(layer.bufferData->frameNumber); @@ -192,8 +191,7 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( if (layer.what & layer_state_t::eInputInfoChanged) { if (layer.windowInfoHandle) { const gui::WindowInfo* inputInfo = layer.windowInfoHandle->getInfo(); - perfetto::protos::LayerState_WindowInfo* windowInfoProto = - proto.mutable_window_info_handle(); + proto::LayerState_WindowInfo* windowInfoProto = proto.mutable_window_info_handle(); windowInfoProto->set_layout_params_flags(inputInfo->layoutParamsFlags.get()); windowInfoProto->set_layout_params_type( static_cast(inputInfo->layoutParamsType)); @@ -206,7 +204,7 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test( gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)); windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor); - perfetto::protos::Transform* transformProto = windowInfoProto->mutable_transform(); + proto::Transform* transformProto = windowInfoProto->mutable_transform(); transformProto->set_dsdx(inputInfo->transform.dsdx()); transformProto->set_dtdx(inputInfo->transform.dtdx()); transformProto->set_dtdy(inputInfo->transform.dtdy()); @@ -221,7 +219,7 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( if (layer.what & layer_state_t::eBackgroundColorChanged) { proto.set_bg_color_alpha(layer.bgColor.a); proto.set_bg_color_dataspace(static_cast(layer.bgColorDataspace)); - perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color(); + proto::LayerState_Color3* colorProto = proto.mutable_color(); colorProto->set_r(layer.bgColor.r); colorProto->set_g(layer.bgColor.g); colorProto->set_b(layer.bgColor.b); @@ -257,13 +255,13 @@ perfetto::protos::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eDropInputModeChanged) { proto.set_drop_input_mode( - static_cast(layer.dropInputMode)); + static_cast(layer.dropInputMode)); } return proto; } -perfetto::protos::DisplayState TransactionProtoParser::toProto(const DisplayState& display) { - perfetto::protos::DisplayState proto; +proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) { + proto::DisplayState proto; proto.set_what(display.what); proto.set_id(mMapper->getDisplayId(display.token)); @@ -287,8 +285,8 @@ perfetto::protos::DisplayState TransactionProtoParser::toProto(const DisplayStat return proto; } -perfetto::protos::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) { - perfetto::protos::LayerCreationArgs proto; +proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) { + proto::LayerCreationArgs proto; proto.set_layer_id(args.sequence); proto.set_name(args.name); proto.set_flags(args.flags); @@ -299,8 +297,7 @@ perfetto::protos::LayerCreationArgs TransactionProtoParser::toProto(const LayerC return proto; } -TransactionState TransactionProtoParser::fromProto( - const perfetto::protos::TransactionState& proto) { +TransactionState TransactionProtoParser::fromProto(const proto::TransactionState& proto) { TransactionState t; t.originPid = proto.pid(); t.originUid = proto.uid(); @@ -326,7 +323,7 @@ TransactionState TransactionProtoParser::fromProto( return t; } -void TransactionProtoParser::fromProto(const perfetto::protos::LayerCreationArgs& proto, +void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto, LayerCreationArgs& outArgs) { outArgs.sequence = proto.layer_id(); @@ -338,7 +335,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerCreationArgs outArgs.layerStackToMirror.id = proto.layer_stack_to_mirror(); } -void TransactionProtoParser::mergeFromProto(const perfetto::protos::LayerState& proto, +void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto, TracingLayerState& outState) { ResolvedComposerState resolvedComposerState; fromProto(proto, resolvedComposerState); @@ -363,7 +360,7 @@ void TransactionProtoParser::mergeFromProto(const perfetto::protos::LayerState& } } -void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto, +void TransactionProtoParser::fromProto(const proto::LayerState& proto, ResolvedComposerState& resolvedComposerState) { auto& layer = resolvedComposerState.state; resolvedComposerState.layerId = proto.layer_id(); @@ -384,7 +381,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto layer.mask = proto.mask(); } if (proto.what() & layer_state_t::eMatrixChanged) { - const perfetto::protos::LayerState_Matrix22& matrixProto = proto.matrix(); + const proto::LayerState_Matrix22& matrixProto = proto.matrix(); layer.matrix.dsdx = matrixProto.dsdx(); layer.matrix.dsdy = matrixProto.dsdy(); layer.matrix.dtdx = matrixProto.dtdx(); @@ -402,7 +399,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto } if (proto.what() & layer_state_t::eColorChanged) { - const perfetto::protos::LayerState_Color3& colorProto = proto.color(); + const proto::LayerState_Color3& colorProto = proto.color(); layer.color.r = colorProto.r(); layer.color.g = colorProto.g(); layer.color.b = colorProto.b(); @@ -420,7 +417,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto LayerProtoHelper::readFromProto(proto.crop(), layer.crop); } if (proto.what() & layer_state_t::eBufferChanged) { - const perfetto::protos::LayerState_BufferData& bufferProto = proto.buffer_data(); + const proto::LayerState_BufferData& bufferProto = proto.buffer_data(); layer.bufferData = std::make_shared(bufferProto.buffer_id(), bufferProto.width(), bufferProto.height(), bufferProto.pixel_format(), @@ -463,7 +460,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto if ((proto.what() & layer_state_t::eInputInfoChanged) && proto.has_window_info_handle()) { gui::WindowInfo inputInfo; - const perfetto::protos::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle(); + const proto::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle(); inputInfo.layoutParamsFlags = static_cast(windowInfoProto.layout_params_flags()); @@ -475,7 +472,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto ftl::Flags(windowInfoProto.input_config()); inputInfo.surfaceInset = windowInfoProto.surface_inset(); inputInfo.globalScaleFactor = windowInfoProto.global_scale_factor(); - const perfetto::protos::Transform& transformProto = windowInfoProto.transform(); + const proto::Transform& transformProto = windowInfoProto.transform(); inputInfo.transform.set(transformProto.dsdx(), transformProto.dtdx(), transformProto.dtdy(), transformProto.dsdy()); inputInfo.transform.set(transformProto.tx(), transformProto.ty()); @@ -488,7 +485,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto if (proto.what() & layer_state_t::eBackgroundColorChanged) { layer.bgColor.a = proto.bg_color_alpha(); layer.bgColorDataspace = static_cast(proto.bg_color_dataspace()); - const perfetto::protos::LayerState_Color3& colorProto = proto.color(); + const proto::LayerState_Color3& colorProto = proto.color(); layer.bgColor.r = colorProto.r(); layer.bgColor.g = colorProto.g(); layer.bgColor.b = colorProto.b(); @@ -528,7 +525,7 @@ void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto } } -DisplayState TransactionProtoParser::fromProto(const perfetto::protos::DisplayState& proto) { +DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) { DisplayState display; display.what = proto.what(); display.token = mMapper->getDisplayHandle(proto.id()); @@ -553,7 +550,7 @@ DisplayState TransactionProtoParser::fromProto(const perfetto::protos::DisplaySt return display; } -void asProto(perfetto::protos::Transform* proto, const ui::Transform& transform) { +void asProto(proto::Transform* proto, const ui::Transform& transform) { proto->set_dsdx(transform.dsdx()); proto->set_dtdx(transform.dtdx()); proto->set_dtdy(transform.dtdy()); @@ -562,9 +559,9 @@ void asProto(perfetto::protos::Transform* proto, const ui::Transform& transform) proto->set_ty(transform.ty()); } -perfetto::protos::DisplayInfo TransactionProtoParser::toProto( - const frontend::DisplayInfo& displayInfo, uint32_t layerStack) { - perfetto::protos::DisplayInfo proto; +proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& displayInfo, + uint32_t layerStack) { + proto::DisplayInfo proto; proto.set_layer_stack(layerStack); proto.set_display_id(displayInfo.info.displayId); proto.set_logical_width(displayInfo.info.logicalWidth); @@ -580,13 +577,12 @@ perfetto::protos::DisplayInfo TransactionProtoParser::toProto( return proto; } -void fromProto2(ui::Transform& outTransform, const perfetto::protos::Transform& proto) { +void fromProto2(ui::Transform& outTransform, const proto::Transform& proto) { outTransform.set(proto.dsdx(), proto.dtdx(), proto.dtdy(), proto.dsdy()); outTransform.set(proto.tx(), proto.ty()); } -frontend::DisplayInfo TransactionProtoParser::fromProto( - const perfetto::protos::DisplayInfo& proto) { +frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo& proto) { frontend::DisplayInfo displayInfo; displayInfo.info.displayId = proto.display_id(); displayInfo.info.logicalWidth = proto.logical_width(); @@ -603,10 +599,10 @@ frontend::DisplayInfo TransactionProtoParser::fromProto( } void TransactionProtoParser::fromProto( - const google::protobuf::RepeatedPtrField& proto, + const google::protobuf::RepeatedPtrField& proto, frontend::DisplayInfos& outDisplayInfos) { outDisplayInfos.clear(); - for (const perfetto::protos::DisplayInfo& displayInfo : proto) { + for (const proto::DisplayInfo& displayInfo : proto) { outDisplayInfos.emplace_or_replace(ui::LayerStack::fromValue(displayInfo.layer_stack()), fromProto(displayInfo)); } diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h index b3ab71cfb5..457c3bec40 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.h +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h @@ -44,25 +44,25 @@ public: TransactionProtoParser(std::unique_ptr provider) : mMapper(std::move(provider)) {} - perfetto::protos::TransactionState toProto(const TransactionState&); - perfetto::protos::TransactionState toProto( - const std::map&); - perfetto::protos::LayerCreationArgs toProto(const LayerCreationArgs& args); - perfetto::protos::LayerState toProto(const ResolvedComposerState&); - static perfetto::protos::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); + proto::TransactionState toProto(const TransactionState&); + proto::TransactionState toProto(const std::map&); + proto::LayerCreationArgs toProto(const LayerCreationArgs& args); + proto::LayerState toProto(const ResolvedComposerState&); + static proto::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); - TransactionState fromProto(const perfetto::protos::TransactionState&); - void mergeFromProto(const perfetto::protos::LayerState&, TracingLayerState& outState); - void fromProto(const perfetto::protos::LayerCreationArgs&, LayerCreationArgs& outArgs); + TransactionState fromProto(const proto::TransactionState&); + void mergeFromProto(const proto::LayerState&, TracingLayerState& outState); + void fromProto(const proto::LayerCreationArgs&, LayerCreationArgs& outArgs); std::unique_ptr mMapper; - static frontend::DisplayInfo fromProto(const perfetto::protos::DisplayInfo&); - static void fromProto(const google::protobuf::RepeatedPtrField&, + static frontend::DisplayInfo fromProto(const proto::DisplayInfo&); + static void fromProto(const google::protobuf::RepeatedPtrField&, frontend::DisplayInfos& outDisplayInfos); private: - perfetto::protos::DisplayState toProto(const DisplayState&); - void fromProto(const perfetto::protos::LayerState&, ResolvedComposerState& out); - DisplayState fromProto(const perfetto::protos::DisplayState&); + proto::DisplayState toProto(const DisplayState&); + void fromProto(const proto::LayerState&, ResolvedComposerState& out); + DisplayState fromProto(const proto::DisplayState&); + }; } // namespace android::surfaceflinger diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp index 8aacbca90c..bc69191cc1 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.cpp +++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp @@ -59,7 +59,7 @@ TransactionTracing::~TransactionTracing() { status_t TransactionTracing::writeToFile(const std::string& filename) { std::scoped_lock lock(mTraceLock); - perfetto::protos::TransactionTraceFile fileProto = createTraceFileProto(); + proto::TransactionTraceFile fileProto = createTraceFileProto(); addStartingStateToProtoLocked(fileProto); return mBuffer.writeToFile(fileProto, filename); } @@ -70,11 +70,10 @@ void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) { mBuffer.setSize(mBufferSizeInBytes); } -perfetto::protos::TransactionTraceFile TransactionTracing::createTraceFileProto() const { - perfetto::protos::TransactionTraceFile proto; - proto.set_magic_number( - uint64_t(perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 | - perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L); +proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { + proto::TransactionTraceFile proto; + proto.set_magic_number(uint64_t(proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 | + proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L); auto timeOffsetNs = static_cast(systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC)); proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs); @@ -90,8 +89,7 @@ void TransactionTracing::dump(std::string& result) const { } void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) { - perfetto::protos::TransactionState* state = - new perfetto::protos::TransactionState(mProtoParser.toProto(transaction)); + proto::TransactionState* state = new proto::TransactionState(mProtoParser.toProto(transaction)); mTransactionQueue.push(state); } @@ -154,7 +152,7 @@ void TransactionTracing::addEntry(const std::vector& committed ATRACE_CALL(); std::scoped_lock lock(mTraceLock); std::vector removedEntries; - perfetto::protos::TransactionTraceEntry entryProto; + proto::TransactionTraceEntry entryProto; while (auto incomingTransaction = mTransactionQueue.pop()) { auto transaction = *incomingTransaction; @@ -213,7 +211,7 @@ void TransactionTracing::addEntry(const std::vector& committed std::make_move_iterator(entries.end())); } - perfetto::protos::TransactionTraceEntry removedEntryProto; + proto::TransactionTraceEntry removedEntryProto; for (const std::string& removedEntry : removedEntries) { removedEntryProto.ParseFromString(removedEntry); updateStartingStateLocked(removedEntryProto); @@ -238,7 +236,7 @@ void TransactionTracing::flush() { base::ScopedLockAssertion assumeLocked(mTraceLock); mTransactionsAddedToBufferCv.wait_for(lock, std::chrono::milliseconds(100), [&]() REQUIRES(mTraceLock) { - perfetto::protos::TransactionTraceEntry entry; + proto::TransactionTraceEntry entry; if (mBuffer.used() > 0) { entry.ParseFromString(mBuffer.back()); } @@ -270,19 +268,19 @@ void TransactionTracing::tryPushToTracingThread() { } void TransactionTracing::updateStartingStateLocked( - const perfetto::protos::TransactionTraceEntry& removedEntry) { + const proto::TransactionTraceEntry& removedEntry) { mStartingTimestamp = removedEntry.elapsed_realtime_nanos(); // Keep track of layer starting state so we can reconstruct the layer state as we purge // transactions from the buffer. - for (const perfetto::protos::LayerCreationArgs& addedLayer : removedEntry.added_layers()) { + for (const proto::LayerCreationArgs& addedLayer : removedEntry.added_layers()) { TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()]; startingState.layerId = addedLayer.layer_id(); mProtoParser.fromProto(addedLayer, startingState.args); } // Merge layer states to starting transaction state. - for (const perfetto::protos::TransactionState& transaction : removedEntry.transactions()) { - for (const perfetto::protos::LayerState& layerState : transaction.layer_changes()) { + for (const proto::TransactionState& transaction : removedEntry.transactions()) { + for (const proto::LayerState& layerState : transaction.layer_changes()) { auto it = mStartingStates.find(layerState.layer_id()); if (it == mStartingStates.end()) { // TODO(b/238781169) make this log fatal when we switch over to using new fe @@ -309,13 +307,12 @@ void TransactionTracing::updateStartingStateLocked( } } -void TransactionTracing::addStartingStateToProtoLocked( - perfetto::protos::TransactionTraceFile& proto) { +void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) { if (mStartingStates.size() == 0) { return; } - perfetto::protos::TransactionTraceEntry* entryProto = proto.add_entry(); + proto::TransactionTraceEntry* entryProto = proto.add_entry(); entryProto->set_elapsed_realtime_nanos(mStartingTimestamp); entryProto->set_vsync_id(0); @@ -324,7 +321,7 @@ void TransactionTracing::addStartingStateToProtoLocked( entryProto->mutable_added_layers()->Add(mProtoParser.toProto(state.args)); } - perfetto::protos::TransactionState transactionProto = mProtoParser.toProto(mStartingStates); + proto::TransactionState transactionProto = mProtoParser.toProto(mStartingStates); transactionProto.set_vsync_id(0); transactionProto.set_post_time(mStartingTimestamp); entryProto->mutable_transactions()->Add(std::move(transactionProto)); @@ -341,9 +338,9 @@ void TransactionTracing::addStartingStateToProtoLocked( } } -perfetto::protos::TransactionTraceFile TransactionTracing::writeToProto() { +proto::TransactionTraceFile TransactionTracing::writeToProto() { std::scoped_lock lock(mTraceLock); - perfetto::protos::TransactionTraceFile proto = createTraceFileProto(); + proto::TransactionTraceFile proto = createTraceFileProto(); addStartingStateToProtoLocked(proto); mBuffer.writeToProto(proto); return proto; diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h index 09fcd8ad96..422b5f3689 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.h +++ b/services/surfaceflinger/Tracing/TransactionTracing.h @@ -85,16 +85,14 @@ private: } mutable std::mutex mTraceLock; - TransactionRingBuffer - mBuffer GUARDED_BY(mTraceLock); + TransactionRingBuffer mBuffer + GUARDED_BY(mTraceLock); size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; - std::unordered_map mQueuedTransactions + std::unordered_map mQueuedTransactions GUARDED_BY(mTraceLock); - LocklessStack mTransactionQueue; + LocklessStack mTransactionQueue; nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock); - std::unordered_map mCreatedLayers - GUARDED_BY(mTraceLock); + std::unordered_map mCreatedLayers GUARDED_BY(mTraceLock); std::map mStartingStates GUARDED_BY(mTraceLock); frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock); @@ -124,19 +122,17 @@ private: std::vector mPendingDestroyedLayers; // only accessed by main thread int64_t mLastUpdatedVsyncId = -1; - perfetto::protos::TransactionTraceFile createTraceFileProto() const; + proto::TransactionTraceFile createTraceFileProto() const; void loop(); void addEntry(const std::vector& committedTransactions, const std::vector& removedLayers) EXCLUDES(mTraceLock); int32_t getLayerIdLocked(const sp& layerHandle) REQUIRES(mTraceLock); void tryPushToTracingThread() EXCLUDES(mMainThreadLock); - void addStartingStateToProtoLocked(perfetto::protos::TransactionTraceFile& proto) - REQUIRES(mTraceLock); - void updateStartingStateLocked(const perfetto::protos::TransactionTraceEntry& entry) - REQUIRES(mTraceLock); + void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock); + void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock); // TEST // Return buffer contents as trace file proto - perfetto::protos::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); + proto::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); }; class TransactionTraceWriter : public Singleton { diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 9471e954d8..321b8baccc 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -40,8 +40,8 @@ namespace android { using namespace ftl::flag_operators; -bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& traceFile, - const char*, bool onlyLastEntry) { +bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, + const char* outputLayersTracePath, bool onlyLastEntry) { if (traceFile.entry_size() == 0) { ALOGD("Trace file is empty"); return false; diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h index a1e5fc894b..e41d1e6e0b 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h @@ -21,7 +21,7 @@ namespace android { class LayerTraceGenerator { public: - bool generate(const perfetto::protos::TransactionTraceFile&, const char* outputLayersTracePath, + bool generate(const proto::TransactionTraceFile&, const char* outputLayersTracePath, bool onlyLastEntry); }; -} // namespace android +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp index 0ff8f98d36..5ca87e4cb3 100644 --- a/services/surfaceflinger/Tracing/tools/main.cpp +++ b/services/surfaceflinger/Tracing/tools/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) { return -1; } - perfetto::protos::TransactionTraceFile transactionTraceFile; + proto::TransactionTraceFile transactionTraceFile; if (!transactionTraceFile.ParseFromIstream(&input)) { std::cout << "Error: Failed to parse " << transactionTracePath; return -1; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 437fd35c15..8a050fdab5 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -455,8 +455,7 @@ public: result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result); - perfetto::protos::LayersProto layersProto = - mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); + LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); mFlinger->dumpOffscreenLayersProto(layersProto); mFlinger->dumpDisplayProto(); diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index a4dc8a058e..7287dd0103 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -13,20 +13,7 @@ cc_library { srcs: [ "LayerProtoParser.cpp", - ], - - static_libs: [ - "libperfetto_client_experimental", - ], - - whole_static_libs: [ - // TODO(b/169779783): move into "static_libs" when the soong issue is fixed - "perfetto_trace_protos", - ], - - export_static_lib_headers: [ - "libperfetto_client_experimental", - "perfetto_trace_protos", + "*.proto", ], shared_libs: [ @@ -37,6 +24,10 @@ cc_library { "libbase", ], + proto: { + export_proto_headers: true, + }, + cppflags: [ "-Werror", "-Wno-unused-parameter", @@ -51,3 +42,22 @@ cc_library { "-Wno-undef", ], } + +java_library_static { + name: "layersprotoslite", + host_supported: true, + proto: { + type: "lite", + include_dirs: ["external/protobuf/src"], + }, + srcs: ["*.proto"], + sdk_version: "core_platform", + target: { + android: { + jarjar_rules: "jarjar-rules.txt", + }, + host: { + static_libs: ["libprotobuf-java-lite"], + }, + }, +} diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 8d48070e13..854084e7f9 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -37,8 +37,7 @@ bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs return lhs->id < rhs->id; } -LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree( - const perfetto::protos::LayersProto& layersProto) { +LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProto& layersProto) { LayerTree layerTree; layerTree.allLayers = generateLayerList(layersProto); @@ -54,7 +53,7 @@ LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree( } std::vector LayerProtoParser::generateLayerList( - const perfetto::protos::LayersProto& layersProto) { + const LayersProto& layersProto) { std::vector layerList; std::unordered_map layerMap; @@ -75,8 +74,7 @@ std::vector LayerProtoParser::generateLayerList( return layerList; } -LayerProtoParser::Layer LayerProtoParser::generateLayer( - const perfetto::protos::LayerProto& layerProto) { +LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerProto) { Layer layer; layer.id = layerProto.id(); layer.name = layerProto.name(); @@ -122,19 +120,17 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer( return layer; } -LayerProtoParser::Region LayerProtoParser::generateRegion( - const perfetto::protos::RegionProto& regionProto) { +LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) { LayerProtoParser::Region region; for (int i = 0; i < regionProto.rect_size(); i++) { - const perfetto::protos::RectProto& rectProto = regionProto.rect(i); + const RectProto& rectProto = regionProto.rect(i); region.rects.push_back(generateRect(rectProto)); } return region; } -LayerProtoParser::Rect LayerProtoParser::generateRect( - const perfetto::protos::RectProto& rectProto) { +LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) { LayerProtoParser::Rect rect; rect.left = rectProto.left(); rect.top = rectProto.top(); @@ -144,8 +140,7 @@ LayerProtoParser::Rect LayerProtoParser::generateRect( return rect; } -LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect( - const perfetto::protos::FloatRectProto& rectProto) { +LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) { LayerProtoParser::FloatRect rect; rect.left = rectProto.left(); rect.top = rectProto.top(); @@ -156,7 +151,7 @@ LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect( } LayerProtoParser::Transform LayerProtoParser::generateTransform( - const perfetto::protos::TransformProto& transformProto) { + const TransformProto& transformProto) { LayerProtoParser::Transform transform; transform.dsdx = transformProto.dsdx(); transform.dtdx = transformProto.dtdx(); @@ -167,7 +162,7 @@ LayerProtoParser::Transform LayerProtoParser::generateTransform( } LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( - const perfetto::protos::ActiveBufferProto& activeBufferProto) { + const ActiveBufferProto& activeBufferProto) { LayerProtoParser::ActiveBuffer activeBuffer; activeBuffer.width = activeBufferProto.width(); activeBuffer.height = activeBufferProto.height(); @@ -177,7 +172,7 @@ LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( return activeBuffer; } -void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto, +void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, std::unordered_map& layerMap) { auto currLayer = layerMap[layerProto.id()]; diff --git a/services/surfaceflinger/layerproto/common.proto b/services/surfaceflinger/layerproto/common.proto new file mode 100644 index 0000000000..5e20d4d0f5 --- /dev/null +++ b/services/surfaceflinger/layerproto/common.proto @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; +package android.surfaceflinger; + +message RegionProto { + reserved 1; // Previously: uint64 id + repeated RectProto rect = 2; +} + +message RectProto { + int32 left = 1; + int32 top = 2; + int32 right = 3; + int32 bottom = 4; +} + +message SizeProto { + int32 w = 1; + int32 h = 2; +} + +message TransformProto { + float dsdx = 1; + float dtdx = 2; + float dsdy = 3; + float dtdy = 4; + int32 type = 5; +} + +message ColorProto { + float r = 1; + float g = 2; + float b = 3; + float a = 4; +} + +message InputWindowInfoProto { + uint32 layout_params_flags = 1; + int32 layout_params_type = 2; + RectProto frame = 3; + RegionProto touchable_region = 4; + + int32 surface_inset = 5; + bool visible = 6; + bool can_receive_keys = 7 [deprecated = true]; + bool focusable = 8; + bool has_wallpaper = 9; + + float global_scale_factor = 10; + float window_x_scale = 11 [deprecated = true]; + float window_y_scale = 12 [deprecated = true]; + + int32 crop_layer_id = 13; + bool replace_touchable_region_with_crop = 14; + RectProto touchable_region_crop = 15; + TransformProto transform = 16; + uint32 input_config = 17; +} + +message BlurRegion { + uint32 blur_radius = 1; + uint32 corner_radius_tl = 2; + uint32 corner_radius_tr = 3; + uint32 corner_radius_bl = 4; + float corner_radius_br = 5; + float alpha = 6; + int32 left = 7; + int32 top = 8; + int32 right = 9; + int32 bottom = 10; +} + +message ColorTransformProto { + // This will be a 4x4 matrix of float values + repeated float val = 1; +} diff --git a/services/surfaceflinger/layerproto/display.proto b/services/surfaceflinger/layerproto/display.proto new file mode 100644 index 0000000000..64de775b8b --- /dev/null +++ b/services/surfaceflinger/layerproto/display.proto @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; + +import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; + +package android.surfaceflinger; + +message DisplayProto { + uint64 id = 1; + + string name = 2; + + uint32 layer_stack = 3; + + SizeProto size = 4; + + RectProto layer_stack_space_rect = 5; + + TransformProto transform = 6; + + bool is_virtual = 7; + + double dpi_x = 8; + + double dpi_y = 9; +} diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h index 4a2ef3ddf8..f560562c94 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h @@ -14,14 +14,11 @@ * limitations under the License. */ -#pragma once - // pragma is used here to disable the warnings emitted from the protobuf // headers. By adding #pragma before including layer.pb.h, it supresses // protobuf warnings, but allows the rest of the files to continuing using // the current flags. // This file should be included instead of directly including layer.b.h #pragma GCC system_header -#include -#include -#include +#include +#include diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index 79c3982dbd..cdc2706ee2 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -131,22 +131,19 @@ public: std::vector topLevelLayers; }; - static LayerTree generateLayerTree(const perfetto::protos::LayersProto& layersProto); + static LayerTree generateLayerTree(const LayersProto& layersProto); static std::string layerTreeToString(const LayerTree& layerTree); private: - static std::vector generateLayerList(const perfetto::protos::LayersProto& layersProto); - static LayerProtoParser::Layer generateLayer(const perfetto::protos::LayerProto& layerProto); - static LayerProtoParser::Region generateRegion( - const perfetto::protos::RegionProto& regionProto); - static LayerProtoParser::Rect generateRect(const perfetto::protos::RectProto& rectProto); - static LayerProtoParser::FloatRect generateFloatRect( - const perfetto::protos::FloatRectProto& rectProto); - static LayerProtoParser::Transform generateTransform( - const perfetto::protos::TransformProto& transformProto); + static std::vector generateLayerList(const LayersProto& layersProto); + static LayerProtoParser::Layer generateLayer(const LayerProto& layerProto); + static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); + static LayerProtoParser::Rect generateRect(const RectProto& rectProto); + static LayerProtoParser::FloatRect generateFloatRect(const FloatRectProto& rectProto); + static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); static LayerProtoParser::ActiveBuffer generateActiveBuffer( - const perfetto::protos::ActiveBufferProto& activeBufferProto); - static void updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto, + const ActiveBufferProto& activeBufferProto); + static void updateChildrenAndRelative(const LayerProto& layerProto, std::unordered_map& layerMap); static std::string layerToString(const LayerProtoParser::Layer* layer); diff --git a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h index ea80ad8f33..3e9ca52fff 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h +++ b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h @@ -14,11 +14,7 @@ * limitations under the License. */ -#pragma once - // disable the warnings emitted from the protobuf headers. This file should be included instead of // directly including the generated header file #pragma GCC system_header -#include -#include -#include +#include diff --git a/services/surfaceflinger/layerproto/jarjar-rules.txt b/services/surfaceflinger/layerproto/jarjar-rules.txt new file mode 100644 index 0000000000..40043a861c --- /dev/null +++ b/services/surfaceflinger/layerproto/jarjar-rules.txt @@ -0,0 +1 @@ +rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto new file mode 100644 index 0000000000..e9add2e1a4 --- /dev/null +++ b/services/surfaceflinger/layerproto/layers.proto @@ -0,0 +1,171 @@ +// Definitions for SurfaceFlinger layers. + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; + +import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; + +package android.surfaceflinger; + +// Contains a list of all layers. +message LayersProto { + repeated LayerProto layers = 1; +} + +// Must match definition in the IComposerClient HAL +enum HwcCompositionType { + // Invalid composition type + INVALID = 0; + // Layer was composited by the client into the client target buffer + CLIENT = 1; + // Layer was composited by the device through hardware overlays + DEVICE = 2; + // Layer was composited by the device using a color + SOLID_COLOR = 3; + // Similar to DEVICE, but the layer position may have been asynchronously set + // through setCursorPosition + CURSOR = 4; + // Layer was composited by the device via a sideband stream. + SIDEBAND = 5; +} + +// Information about each layer. +message LayerProto { + // unique id per layer. + int32 id = 1; + // unique name per layer. + string name = 2; + // list of children this layer may have. May be empty. + repeated int32 children = 3; + // list of layers that are z order relative to this layer. + repeated int32 relatives = 4; + // The type of layer, ex Color, Layer + string type = 5; + RegionProto transparent_region = 6; + RegionProto visible_region = 7; + RegionProto damage_region = 8; + uint32 layer_stack = 9; + // The layer's z order. Can be z order in layer stack, relative to parent, + // or relative to another layer specified in zOrderRelative. + int32 z = 10; + // The layer's position on the display. + PositionProto position = 11; + // The layer's requested position. + PositionProto requested_position = 12; + // The layer's size. + SizeProto size = 13; + // The layer's crop in it's own bounds. + RectProto crop = 14; + // The layer's crop in it's parent's bounds. + RectProto final_crop = 15 [deprecated=true]; + bool is_opaque = 16; + bool invalidate = 17; + string dataspace = 18; + string pixel_format = 19; + // The layer's actual color. + ColorProto color = 20; + // The layer's requested color. + ColorProto requested_color = 21; + // Can be any combination of + // hidden = 0x01 + // opaque = 0x02, + // secure = 0x80, + uint32 flags = 22; + // The layer's actual transform + TransformProto transform = 23; + // The layer's requested transform. + TransformProto requested_transform = 24; + // The parent layer. This value can be null if there is no parent. + int32 parent = 25; + // The layer that this layer has a z order relative to. This value can be null. + int32 z_order_relative_of = 26; + // This value can be null if there's nothing to draw. + ActiveBufferProto active_buffer = 27; + // The number of frames available. + int32 queued_frames = 28; + bool refresh_pending = 29; + // The layer's composer backend destination frame + RectProto hwc_frame = 30; + // The layer's composer backend source crop + FloatRectProto hwc_crop = 31; + // The layer's composer backend transform + int32 hwc_transform = 32; + int32 window_type = 33 [deprecated=true]; + int32 app_id = 34 [deprecated=true]; + // The layer's composition type + HwcCompositionType hwc_composition_type = 35; + // If it's a buffer layer, indicate if the content is protected + bool is_protected = 36; + // Current frame number being rendered. + uint64 curr_frame = 37; + // A list of barriers that the layer is waiting to update state. + repeated BarrierLayerProto barrier_layer = 38; + // If active_buffer is not null, record its transform. + TransformProto buffer_transform = 39; + int32 effective_scaling_mode = 40; + // Layer's corner radius. + float corner_radius = 41; + // Metadata map. May be empty. + map metadata = 42; + + TransformProto effective_transform = 43; + FloatRectProto source_bounds = 44; + FloatRectProto bounds = 45; + FloatRectProto screen_bounds = 46; + + InputWindowInfoProto input_window_info = 47; + + // Crop used to draw the rounded corner. + FloatRectProto corner_radius_crop = 48; + + // length of the shadow to draw around the layer, it may be set on the + // layer or set by a parent layer. + float shadow_radius = 49; + ColorTransformProto color_transform = 50; + + bool is_relative_of = 51; + // Layer's background blur radius in pixels. + int32 background_blur_radius = 52; + + uint32 owner_uid = 53; + + // Regions of a layer, where blur should be applied. + repeated BlurRegion blur_regions = 54; + + bool is_trusted_overlay = 55; + + // Corner radius explicitly set on layer rather than inherited + float requested_corner_radius = 56; + + RectProto destination_frame = 57; + + uint32 original_id = 58; +} + +message PositionProto { + float x = 1; + float y = 2; +} + +message FloatRectProto { + float left = 1; + float top = 2; + float right = 3; + float bottom = 4; +} + +message ActiveBufferProto { + uint32 width = 1; + uint32 height = 2; + uint32 stride = 3; + int32 format = 4; + uint64 usage = 5; +} + +message BarrierLayerProto { + // layer id the barrier is waiting on. + int32 id = 1; + // frame number the barrier is waiting on. + uint64 frame_number = 2; +} + diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto new file mode 100644 index 0000000000..804a4994ee --- /dev/null +++ b/services/surfaceflinger/layerproto/layerstrace.proto @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; + +import "frameworks/native/services/surfaceflinger/layerproto/layers.proto"; +import "frameworks/native/services/surfaceflinger/layerproto/display.proto"; + +package android.surfaceflinger; + +/* represents a file full of surface flinger trace entries. + Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such + that they can be easily identified. */ +message LayersTraceFileProto { + + /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L + (this is needed because enums have to be 32 bits and there's no nice way to put 64bit + constants into .proto files. */ + enum MagicNumber { + INVALID = 0; + MAGIC_NUMBER_L = 0x5452594c; /* LYRT (little-endian ASCII) */ + MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ + } + + optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ + repeated LayersTraceProto entry = 2; + + /* offset between real-time clock and elapsed time clock in nanoseconds. + Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */ + optional fixed64 real_to_elapsed_time_offset_nanos = 3; +} + +/* one layers trace entry. */ +message LayersTraceProto { + /* required: elapsed realtime in nanos since boot of when this entry was logged */ + optional sfixed64 elapsed_realtime_nanos = 1; + + /* where the trace originated */ + optional string where = 2; + + optional LayersProto layers = 3; + + // Blob for the current HWC information for all layers, reported by dumpsys. + optional string hwc_blob = 4; + + /* Includes state sent during composition like visible region and composition type. */ + optional bool excludes_composition_state = 5; + + /* Number of missed entries since the last entry was recorded. */ + optional uint32 missed_entries = 6; + + repeated DisplayProto displays = 7; + + optional int64 vsync_id = 8; +} diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto new file mode 100644 index 0000000000..d03afa05ab --- /dev/null +++ b/services/surfaceflinger/layerproto/transactions.proto @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +option optimize_for = LITE_RUNTIME; + +import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; + +package android.surfaceflinger.proto; + +/* Represents a file full of surface flinger transactions. + Encoded, it should start with 0x54 0x4E 0x58 0x54 0x52 0x41 0x43 0x45 (.TNXTRACE), such + that they can be easily identified. */ +message TransactionTraceFile { + /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L + (this is needed because enums have to be 32 bits and there's no nice way to put 64bit + constants into .proto files. */ + enum MagicNumber { + INVALID = 0; + MAGIC_NUMBER_L = 0x54584E54; /* TNXT (little-endian ASCII) */ + MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ + } + + fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ + repeated TransactionTraceEntry entry = 2; + + /* offset between real-time clock and elapsed time clock in nanoseconds. + Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */ + fixed64 real_to_elapsed_time_offset_nanos = 3; + uint32 version = 4; +} + +message TransactionTraceEntry { + int64 elapsed_realtime_nanos = 1; + int64 vsync_id = 2; + repeated TransactionState transactions = 3; + repeated LayerCreationArgs added_layers = 4; + repeated uint32 destroyed_layers = 5; + repeated DisplayState added_displays = 6; + repeated int32 removed_displays = 7; + repeated uint32 destroyed_layer_handles = 8; + bool displays_changed = 9; + repeated DisplayInfo displays = 10; +} + +message DisplayInfo { + uint32 layer_stack = 1; + int32 display_id = 2; + int32 logical_width = 3; + int32 logical_height = 4; + Transform transform_inverse = 5; + Transform transform = 6; + bool receives_input = 7; + bool is_secure = 8; + bool is_primary = 9; + bool is_virtual = 10; + int32 rotation_flags = 11; + int32 transform_hint = 12; + +} + +message LayerCreationArgs { + uint32 layer_id = 1; + string name = 2; + uint32 flags = 3; + uint32 parent_id = 4; + uint32 mirror_from_id = 5; + bool add_to_root = 6; + uint32 layer_stack_to_mirror = 7; +} + +message Transform { + float dsdx = 1; + float dtdx = 2; + float dtdy = 3; + float dsdy = 4; + float tx = 5; + float ty = 6; +} + +message TransactionState { + int32 pid = 1; + int32 uid = 2; + int64 vsync_id = 3; + int32 input_event_id = 4; + int64 post_time = 5; + uint64 transaction_id = 6; + repeated LayerState layer_changes = 7; + repeated DisplayState display_changes = 8; + repeated uint64 merged_transaction_ids = 9; +} + +// Keep insync with layer_state_t +message LayerState { + uint32 layer_id = 1; + // Changes are split into ChangesLsb and ChangesMsb. First 32 bits are in ChangesLsb + // and the next 32 bits are in ChangesMsb. This is needed because enums have to be + // 32 bits and there's no nice way to put 64bit constants into .proto files. + enum ChangesLsb { + eChangesLsbNone = 0; + ePositionChanged = 0x00000001; + eLayerChanged = 0x00000002; + // unused = 0x00000004; + eAlphaChanged = 0x00000008; + + eMatrixChanged = 0x00000010; + eTransparentRegionChanged = 0x00000020; + eFlagsChanged = 0x00000040; + eLayerStackChanged = 0x00000080; + + eReleaseBufferListenerChanged = 0x00000400; + eShadowRadiusChanged = 0x00000800; + + eBufferCropChanged = 0x00002000; + eRelativeLayerChanged = 0x00004000; + eReparent = 0x00008000; + + eColorChanged = 0x00010000; + eBufferTransformChanged = 0x00040000; + eTransformToDisplayInverseChanged = 0x00080000; + + eCropChanged = 0x00100000; + eBufferChanged = 0x00200000; + eAcquireFenceChanged = 0x00400000; + eDataspaceChanged = 0x00800000; + + eHdrMetadataChanged = 0x01000000; + eSurfaceDamageRegionChanged = 0x02000000; + eApiChanged = 0x04000000; + eSidebandStreamChanged = 0x08000000; + + eColorTransformChanged = 0x10000000; + eHasListenerCallbacksChanged = 0x20000000; + eInputInfoChanged = 0x40000000; + eCornerRadiusChanged = -2147483648; // 0x80000000; (proto stores enums as signed int) + }; + enum ChangesMsb { + eChangesMsbNone = 0; + eDestinationFrameChanged = 0x1; + eCachedBufferChanged = 0x2; + eBackgroundColorChanged = 0x4; + eMetadataChanged = 0x8; + eColorSpaceAgnosticChanged = 0x10; + eFrameRateSelectionPriority = 0x20; + eFrameRateChanged = 0x40; + eBackgroundBlurRadiusChanged = 0x80; + eProducerDisconnect = 0x100; + eFixedTransformHintChanged = 0x200; + eFrameNumberChanged = 0x400; + eBlurRegionsChanged = 0x800; + eAutoRefreshChanged = 0x1000; + eStretchChanged = 0x2000; + eTrustedOverlayChanged = 0x4000; + eDropInputModeChanged = 0x8000; + }; + uint64 what = 2; + float x = 3; + float y = 4; + int32 z = 5; + uint32 w = 6; + uint32 h = 7; + uint32 layer_stack = 8; + + enum Flags { + eFlagsNone = 0; + eLayerHidden = 0x01; + eLayerOpaque = 0x02; + eLayerSkipScreenshot = 0x40; + eLayerSecure = 0x80; + eEnableBackpressure = 0x100; + eLayerIsDisplayDecoration = 0x200; + }; + uint32 flags = 9; + uint32 mask = 10; + + message Matrix22 { + float dsdx = 1; + float dtdx = 2; + float dtdy = 3; + float dsdy = 4; + }; + Matrix22 matrix = 11; + float corner_radius = 12; + uint32 background_blur_radius = 13; + uint32 parent_id = 14; + uint32 relative_parent_id = 15; + + float alpha = 16; + message Color3 { + float r = 1; + float g = 2; + float b = 3; + } + Color3 color = 17; + RegionProto transparent_region = 18; + uint32 transform = 19; + bool transform_to_display_inverse = 20; + RectProto crop = 21; + + message BufferData { + uint64 buffer_id = 1; + uint32 width = 2; + uint32 height = 3; + uint64 frame_number = 4; + + enum BufferDataChange { + BufferDataChangeNone = 0; + fenceChanged = 0x01; + frameNumberChanged = 0x02; + cachedBufferChanged = 0x04; + } + uint32 flags = 5; + uint64 cached_buffer_id = 6; + + enum PixelFormat { + PIXEL_FORMAT_UNKNOWN = 0; + PIXEL_FORMAT_CUSTOM = -4; + PIXEL_FORMAT_TRANSLUCENT = -3; + PIXEL_FORMAT_TRANSPARENT = -2; + PIXEL_FORMAT_OPAQUE = -1; + PIXEL_FORMAT_RGBA_8888 = 1; + PIXEL_FORMAT_RGBX_8888 = 2; + PIXEL_FORMAT_RGB_888 = 3; + PIXEL_FORMAT_RGB_565 = 4; + PIXEL_FORMAT_BGRA_8888 = 5; + PIXEL_FORMAT_RGBA_5551 = 6; + PIXEL_FORMAT_RGBA_4444 = 7; + PIXEL_FORMAT_RGBA_FP16 = 22; + PIXEL_FORMAT_RGBA_1010102 = 43; + PIXEL_FORMAT_R_8 = 0x38; + } + PixelFormat pixel_format = 7; + uint64 usage = 8; + } + BufferData buffer_data = 22; + int32 api = 23; + bool has_sideband_stream = 24; + ColorTransformProto color_transform = 25; + repeated BlurRegion blur_regions = 26; + + message WindowInfo { + uint32 layout_params_flags = 1; + int32 layout_params_type = 2; + RegionProto touchable_region = 3; + int32 surface_inset = 4; + bool focusable = 5; // unused + bool has_wallpaper = 6; // unused + float global_scale_factor = 7; + uint32 crop_layer_id = 8; + bool replace_touchable_region_with_crop = 9; + RectProto touchable_region_crop = 10; + Transform transform = 11; + uint32 input_config = 12; + } + WindowInfo window_info_handle = 27; + float bg_color_alpha = 28; + int32 bg_color_dataspace = 29; + bool color_space_agnostic = 30; + float shadow_radius = 31; + int32 frame_rate_selection_priority = 32; + float frame_rate = 33; + int32 frame_rate_compatibility = 34; + int32 change_frame_rate_strategy = 35; + uint32 fixed_transform_hint = 36; + uint64 frame_number = 37; + bool auto_refresh = 38; + bool is_trusted_overlay = 39; + RectProto buffer_crop = 40; + RectProto destination_frame = 41; + + enum DropInputMode { + NONE = 0; + ALL = 1; + OBSCURED = 2; + }; + DropInputMode drop_input_mode = 42; +} + +message DisplayState { + enum Changes { + eChangesNone = 0; + eSurfaceChanged = 0x01; + eLayerStackChanged = 0x02; + eDisplayProjectionChanged = 0x04; + eDisplaySizeChanged = 0x08; + eFlagsChanged = 0x10; + }; + int32 id = 1; + uint32 what = 2; + uint32 flags = 3; + uint32 layer_stack = 4; + uint32 orientation = 5; + RectProto layer_stack_space_rect = 6; + RectProto oriented_display_space_rect = 7; + uint32 width = 8; + uint32 height = 9; +} diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index b30df5ef15..03201f7937 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -51,9 +51,9 @@ TEST(SurfaceFlingerStress, create_and_destroy) { } } -perfetto::protos::LayersProto generateLayerProto() { - perfetto::protos::LayersProto layersProto; - std::array layers = {}; +surfaceflinger::LayersProto generateLayerProto() { + surfaceflinger::LayersProto layersProto; + std::array layers = {}; for (size_t i = 0; i < layers.size(); ++i) { layers[i] = layersProto.add_layers(); layers[i]->set_id(i); @@ -103,7 +103,7 @@ TEST(LayerProtoStress, mem_info) { cmd += std::to_string(getpid()); system(cmd.c_str()); for (int i = 0; i < 100000; i++) { - perfetto::protos::LayersProto layersProto = generateLayerProto(); + surfaceflinger::LayersProto layersProto = generateLayerProto(); auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto); surfaceflinger::LayerProtoParser::layerTreeToString(layerTree); } diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp index 333768a92a..b8a5e79a38 100644 --- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp +++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp @@ -149,7 +149,7 @@ static LayerInfo getLayerInfoFromProto(::android::surfaceflinger::LayerProto& pr } static std::vector getLayerInfosFromProto( - perfetto::protos::pbzero::LayersSnapshotProto& entry) { + android::surfaceflinger::LayersTraceProto& entry) { std::unordered_map snapshotIdToLayerId; std::vector layers; layers.reserve(static_cast(entry.layers().layers_size())); @@ -267,4 +267,4 @@ int main(int argc, char** argv) { } ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp index cbb597af69..a95a6453d5 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -85,7 +85,7 @@ TEST(TransactionProtoParserTest, parse) { TransactionProtoParser parser(std::make_unique(displayHandle)); - perfetto::protos::TransactionState proto = parser.toProto(t1); + proto::TransactionState proto = parser.toProto(t1); TransactionState t2 = parser.fromProto(proto); ASSERT_EQ(t1.originPid, t2.originPid); @@ -119,7 +119,7 @@ TEST(TransactionProtoParserTest, parseDisplayInfo) { d1.transformHint = ui::Transform::ROT_90; const uint32_t layerStack = 2; - google::protobuf::RepeatedPtrField displayProtos; + google::protobuf::RepeatedPtrField displayProtos; auto displayInfoProto = displayProtos.Add(); *displayInfoProto = TransactionProtoParser::toProto(d1, layerStack); frontend::DisplayInfos displayInfos; diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp index 7981224b5c..71a2d2b9a6 100644 --- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp @@ -37,11 +37,11 @@ protected: TransactionTracing mTracing; void flush() { mTracing.flush(); } - perfetto::protos::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } + proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } - perfetto::protos::TransactionTraceEntry bufferFront() { + proto::TransactionTraceEntry bufferFront() { std::scoped_lock lock(mTracing.mTraceLock); - perfetto::protos::TransactionTraceEntry entry; + proto::TransactionTraceEntry entry; entry.ParseFromString(mTracing.mBuffer.front()); return entry; } @@ -59,7 +59,7 @@ protected: flush(); } - void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto, + void verifyEntry(const proto::TransactionTraceEntry& actualProto, const std::vector& expectedTransactions, int64_t expectedVsyncId) { EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId); @@ -117,7 +117,7 @@ TEST_F(TransactionTracingTest, addTransactions) { mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false); flush(); - perfetto::protos::TransactionTraceFile proto = writeToProto(); + proto::TransactionTraceFile proto = writeToProto(); ASSERT_EQ(proto.entry().size(), 2); verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId); verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId); @@ -203,7 +203,7 @@ TEST_F(TransactionTracingLayerHandlingTest, addStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - perfetto::protos::TransactionTraceFile proto = writeToProto(); + proto::TransactionTraceFile proto = writeToProto(); // verify we can still retrieve the layer change from the first entry containing starting // states. EXPECT_GT(proto.entry().size(), 0); @@ -221,7 +221,7 @@ TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - perfetto::protos::TransactionTraceFile proto = writeToProto(); + proto::TransactionTraceFile proto = writeToProto(); // verify starting states are updated correctly EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41); } @@ -231,7 +231,7 @@ TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) { queueAndCommitTransaction(++mVsyncId); } - perfetto::protos::TransactionTraceFile proto = writeToProto(); + proto::TransactionTraceFile proto = writeToProto(); // verify the child layer has been removed from the trace EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1); EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId); @@ -242,7 +242,7 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) { while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - perfetto::protos::TransactionTraceFile proto = writeToProto(); + proto::TransactionTraceFile proto = writeToProto(); // verify we have two starting states EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2); @@ -302,7 +302,7 @@ protected: }; TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { - perfetto::protos::TransactionTraceFile proto = writeToProto(); + proto::TransactionTraceFile proto = writeToProto(); // We don't have any starting states since no layer was removed from. EXPECT_EQ(proto.entry().size(), 1); @@ -317,18 +317,18 @@ TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { // Verify we can write the layers traces by entry to reduce mem pressure // on the system when generating large traces. TEST(LayerTraceTest, canStreamLayersTrace) { - perfetto::protos::LayersTraceFileProto inProto = LayerTracing::createTraceFileProto(); + LayersTraceFileProto inProto = LayerTracing::createTraceFileProto(); inProto.add_entry(); inProto.add_entry(); std::string output; inProto.SerializeToString(&output); - perfetto::protos::LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto(); + LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto(); inProto2.add_entry(); std::string output2; inProto2.SerializeToString(&output2); - perfetto::protos::LayersTraceFileProto outProto; + LayersTraceFileProto outProto; outProto.ParseFromString(output + output2); // magic? EXPECT_EQ(outProto.entry().size(), 3); -- cgit v1.2.3-59-g8ed1b From 4ba343c8885c8956fba9c20003651f7a9c8d8256 Mon Sep 17 00:00:00 2001 From: Kean Mariotti Date: Wed, 19 Apr 2023 13:31:02 +0000 Subject: Revert^2 Move proto definitions to external/perfetto This commit moves the layer and transaction .proto files to external/perfetto/protos/perfetto/trace/android/. Test: atest libsurfaceflinger_unittest && atest transactiontrace_testsuite Bug: b/284424784 Change-Id: Ia7e446c528d188c748a800fbf16ab3b8b9a7b9d1 --- services/surfaceflinger/Layer.cpp | 26 +- services/surfaceflinger/Layer.h | 12 +- services/surfaceflinger/LayerProtoHelper.cpp | 83 +++--- services/surfaceflinger/LayerProtoHelper.h | 62 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 29 +- services/surfaceflinger/SurfaceFlinger.h | 10 +- .../Tracing/TransactionProtoParser.cpp | 82 +++--- .../Tracing/TransactionProtoParser.h | 28 +- .../surfaceflinger/Tracing/TransactionTracing.cpp | 39 +-- .../surfaceflinger/Tracing/TransactionTracing.h | 22 +- .../Tracing/tools/LayerTraceGenerator.cpp | 4 +- .../Tracing/tools/LayerTraceGenerator.h | 4 +- services/surfaceflinger/Tracing/tools/main.cpp | 2 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 3 +- services/surfaceflinger/layerproto/Android.bp | 38 +-- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 25 +- services/surfaceflinger/layerproto/common.proto | 92 ------ services/surfaceflinger/layerproto/display.proto | 42 --- .../include/layerproto/LayerProtoHeader.h | 7 +- .../include/layerproto/LayerProtoParser.h | 21 +- .../include/layerproto/TransactionProto.h | 6 +- .../surfaceflinger/layerproto/jarjar-rules.txt | 1 - services/surfaceflinger/layerproto/layers.proto | 171 ------------ .../surfaceflinger/layerproto/layerstrace.proto | 69 ----- .../surfaceflinger/layerproto/transactions.proto | 310 --------------------- services/surfaceflinger/tests/Stress_test.cpp | 8 +- .../tests/tracing/TransactionTraceTestSuite.cpp | 4 +- .../tests/unittests/TransactionProtoParserTest.cpp | 4 +- .../tests/unittests/TransactionTracingTest.cpp | 26 +- 29 files changed, 296 insertions(+), 934 deletions(-) delete mode 100644 services/surfaceflinger/layerproto/common.proto delete mode 100644 services/surfaceflinger/layerproto/display.proto delete mode 100644 services/surfaceflinger/layerproto/jarjar-rules.txt delete mode 100644 services/surfaceflinger/layerproto/layers.proto delete mode 100644 services/surfaceflinger/layerproto/layerstrace.proto delete mode 100644 services/surfaceflinger/layerproto/transactions.proto (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cdf7cff76d..d4babdbd79 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -139,7 +139,7 @@ using gui::WindowInfo; using PresentState = frametimeline::SurfaceFrame::PresentState; -Layer::Layer(const LayerCreationArgs& args) +Layer::Layer(const surfaceflinger::LayerCreationArgs& args) : sequence(args.sequence), mFlinger(sp::fromExisting(args.flinger)), mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)), @@ -1000,8 +1000,8 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; std::string name = mName + "BackgroundColorLayer"; mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer( - LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, - LayerMetadata())); + surfaceflinger::LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, + LayerMetadata())); // add to child list addChild(mDrawingState.bgColorLayer); @@ -2203,8 +2203,9 @@ void Layer::setInputInfo(const WindowInfo& info) { setTransactionFlags(eTransactionNeeded); } -LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { - LayerProto* layerProto = layersProto.add_layers(); +perfetto::protos::LayerProto* Layer::writeToProto(perfetto::protos::LayersProto& layersProto, + uint32_t traceFlags) { + perfetto::protos::LayerProto* layerProto = layersProto.add_layers(); writeToProtoDrawingState(layerProto); writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); @@ -2221,20 +2222,22 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { return layerProto; } -void Layer::writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack) { +void Layer::writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto, + ui::LayerStack layerStack) { ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread. ftl::FakeGuard mainThreadGuard(kMainThreadContext); // Only populate for the primary display. if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) { const auto compositionType = getCompositionType(*display); - layerProto->set_hwc_composition_type(static_cast(compositionType)); + layerProto->set_hwc_composition_type( + static_cast(compositionType)); LayerProtoHelper::writeToProto(getVisibleRegion(display), [&]() { return layerProto->mutable_visible_region(); }); } } -void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { +void Layer::writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo) { const ui::Transform transform = getTransform(); auto buffer = getExternalTexture(); if (buffer != nullptr) { @@ -2273,8 +2276,8 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { layerInfo->set_shadow_radius(mEffectiveShadowRadius); } -void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, - uint32_t traceFlags) { +void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, + LayerVector::StateSet stateSet, uint32_t traceFlags) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mDrawingState; @@ -3630,7 +3633,8 @@ Rect Layer::computeBufferCrop(const State& s) { } sp Layer::createClone(uint32_t mirrorRootId) { - LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()); + surfaceflinger::LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, + LayerMetadata()); sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->setInitialValuesForClone(sp::fromExisting(this), mirrorRootId); return layer; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 7b6c56b6a8..dc4ceb0bfa 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -235,7 +235,7 @@ public: bool useVsyncIdForRefreshRateSelection = false; }; - explicit Layer(const LayerCreationArgs& args); + explicit Layer(const surfaceflinger::LayerCreationArgs& args); virtual ~Layer(); static bool isLayerFocusedBasedOnPriority(int32_t priority); @@ -634,17 +634,19 @@ public: bool isRemovedFromCurrentState() const; - LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags); - void writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack); + perfetto::protos::LayerProto* writeToProto(perfetto::protos::LayersProto& layersProto, + uint32_t traceFlags); + void writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto, + ui::LayerStack layerStack); // Write states that are modified by the main thread. This includes drawing // state as well as buffer data. This should be called in the main or tracing // thread. - void writeToProtoDrawingState(LayerProto* layerInfo); + void writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo); // Write drawing or current state. If writing current state, the caller should hold the // external mStateLock. If writing drawing state, this function should be called on the // main or tracing thread. - void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet, + void writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, LayerVector::StateSet, uint32_t traceFlags = LayerTracing::TRACE_ALL); gui::WindowInfo::Type getWindowType() const { return mWindowType; } diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 341f041086..144e1f5abf 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -29,28 +29,30 @@ using gui::WindowInfo; namespace surfaceflinger { -void LayerProtoHelper::writePositionToProto(const float x, const float y, - std::function getPositionProto) { +void LayerProtoHelper::writePositionToProto( + const float x, const float y, + std::function getPositionProto) { if (x != 0 || y != 0) { // Use a lambda do avoid writing the object header when the object is empty - PositionProto* position = getPositionProto(); + perfetto::protos::PositionProto* position = getPositionProto(); position->set_x(x); position->set_y(y); } } -void LayerProtoHelper::writeSizeToProto(const uint32_t w, const uint32_t h, - std::function getSizeProto) { +void LayerProtoHelper::writeSizeToProto( + const uint32_t w, const uint32_t h, + std::function getSizeProto) { if (w != 0 || h != 0) { // Use a lambda do avoid writing the object header when the object is empty - SizeProto* size = getSizeProto(); + perfetto::protos::SizeProto* size = getSizeProto(); size->set_w(w); size->set_h(h); } } -void LayerProtoHelper::writeToProto(const Region& region, - std::function getRegionProto) { +void LayerProtoHelper::writeToProto( + const Region& region, std::function getRegionProto) { if (region.isEmpty()) { return; } @@ -58,7 +60,8 @@ void LayerProtoHelper::writeToProto(const Region& region, writeToProto(region, getRegionProto()); } -void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) { +void LayerProtoHelper::writeToProto(const Region& region, + perfetto::protos::RegionProto* regionProto) { if (region.isEmpty()) { return; } @@ -72,7 +75,8 @@ void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionPro } } -void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& outRegion) { +void LayerProtoHelper::readFromProto(const perfetto::protos::RegionProto& regionProto, + Region& outRegion) { for (int i = 0; i < regionProto.rect_size(); i++) { Rect rect; readFromProto(regionProto.rect(i), rect); @@ -80,32 +84,34 @@ void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& out } } -void LayerProtoHelper::writeToProto(const Rect& rect, std::function getRectProto) { +void LayerProtoHelper::writeToProto(const Rect& rect, + std::function getRectProto) { if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) { // Use a lambda do avoid writing the object header when the object is empty writeToProto(rect, getRectProto()); } } -void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) { +void LayerProtoHelper::writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto) { rectProto->set_left(rect.left); rectProto->set_top(rect.top); rectProto->set_bottom(rect.bottom); rectProto->set_right(rect.right); } -void LayerProtoHelper::readFromProto(const RectProto& proto, Rect& outRect) { +void LayerProtoHelper::readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect) { outRect.left = proto.left(); outRect.top = proto.top(); outRect.bottom = proto.bottom(); outRect.right = proto.right(); } -void LayerProtoHelper::writeToProto(const FloatRect& rect, - std::function getFloatRectProto) { +void LayerProtoHelper::writeToProto( + const FloatRect& rect, + std::function getFloatRectProto) { if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) { // Use a lambda do avoid writing the object header when the object is empty - FloatRectProto* rectProto = getFloatRectProto(); + perfetto::protos::FloatRectProto* rectProto = getFloatRectProto(); rectProto->set_left(rect.left); rectProto->set_top(rect.top); rectProto->set_bottom(rect.bottom); @@ -113,10 +119,11 @@ void LayerProtoHelper::writeToProto(const FloatRect& rect, } } -void LayerProtoHelper::writeToProto(const half4 color, std::function getColorProto) { +void LayerProtoHelper::writeToProto(const half4 color, + std::function getColorProto) { if (color.r != 0 || color.g != 0 || color.b != 0 || color.a != 0) { // Use a lambda do avoid writing the object header when the object is empty - ColorProto* colorProto = getColorProto(); + perfetto::protos::ColorProto* colorProto = getColorProto(); colorProto->set_r(color.r); colorProto->set_g(color.g); colorProto->set_b(color.b); @@ -125,7 +132,7 @@ void LayerProtoHelper::writeToProto(const half4 color, std::functionset_type(type); @@ -141,7 +148,7 @@ void LayerProtoHelper::writeToProtoDeprecated(const ui::Transform& transform, } void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform, - TransformProto* transformProto) { + perfetto::protos::TransformProto* transformProto) { const uint32_t type = transform.getType() | (transform.getOrientation() << 8); transformProto->set_type(type); @@ -156,12 +163,13 @@ void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform, } } -void LayerProtoHelper::writeToProto(const renderengine::ExternalTexture& buffer, - std::function getActiveBufferProto) { +void LayerProtoHelper::writeToProto( + const renderengine::ExternalTexture& buffer, + std::function getActiveBufferProto) { if (buffer.getWidth() != 0 || buffer.getHeight() != 0 || buffer.getUsage() != 0 || buffer.getPixelFormat() != 0) { // Use a lambda do avoid writing the object header when the object is empty - ActiveBufferProto* activeBufferProto = getActiveBufferProto(); + auto* activeBufferProto = getActiveBufferProto(); activeBufferProto->set_width(buffer.getWidth()); activeBufferProto->set_height(buffer.getHeight()); activeBufferProto->set_stride(buffer.getUsage()); @@ -171,12 +179,12 @@ void LayerProtoHelper::writeToProto(const renderengine::ExternalTexture& buffer, void LayerProtoHelper::writeToProto( const WindowInfo& inputInfo, const wp& touchableRegionBounds, - std::function getInputWindowInfoProto) { + std::function getInputWindowInfoProto) { if (inputInfo.token == nullptr) { return; } - InputWindowInfoProto* proto = getInputWindowInfoProto(); + perfetto::protos::InputWindowInfoProto* proto = getInputWindowInfoProto(); proto->set_layout_params_flags(inputInfo.layoutParamsFlags.get()); proto->set_input_config(inputInfo.inputConfig.get()); using U = std::underlying_type_t; @@ -209,7 +217,8 @@ void LayerProtoHelper::writeToProto( } } -void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto) { +void LayerProtoHelper::writeToProto(const mat4 matrix, + perfetto::protos::ColorTransformProto* colorTransformProto) { for (int i = 0; i < mat4::ROW_SIZE; i++) { for (int j = 0; j < mat4::COL_SIZE; j++) { colorTransformProto->add_val(matrix[i][j]); @@ -217,7 +226,8 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colo } } -void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix) { +void LayerProtoHelper::readFromProto( + const perfetto::protos::ColorTransformProto& colorTransformProto, mat4& matrix) { for (int i = 0; i < mat4::ROW_SIZE; i++) { for (int j = 0; j < mat4::COL_SIZE; j++) { matrix[i][j] = colorTransformProto.val(i * mat4::COL_SIZE + j); @@ -225,7 +235,8 @@ void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformPr } } -void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion* proto) { +void LayerProtoHelper::writeToProto(const android::BlurRegion region, + perfetto::protos::BlurRegion* proto) { proto->set_blur_radius(region.blurRadius); proto->set_corner_radius_tl(region.cornerRadiusTL); proto->set_corner_radius_tr(region.cornerRadiusTR); @@ -238,7 +249,8 @@ void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion proto->set_bottom(region.bottom); } -void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion) { +void LayerProtoHelper::readFromProto(const perfetto::protos::BlurRegion& proto, + android::BlurRegion& outRegion) { outRegion.blurRadius = proto.blur_radius(); outRegion.cornerRadiusTL = proto.corner_radius_tl(); outRegion.cornerRadiusTR = proto.corner_radius_tr(); @@ -251,7 +263,8 @@ void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegio outRegion.bottom = proto.bottom(); } -LayersProto LayerProtoFromSnapshotGenerator::generate(const frontend::LayerHierarchy& root) { +perfetto::protos::LayersProto LayerProtoFromSnapshotGenerator::generate( + const frontend::LayerHierarchy& root) { mLayersProto.clear_layers(); std::unordered_set stackIdsToSkip; if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) { @@ -310,7 +323,7 @@ frontend::LayerSnapshot* LayerProtoFromSnapshotGenerator::getSnapshot( void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( const frontend::LayerHierarchy& root, frontend::LayerHierarchy::TraversalPath& path) { using Variant = frontend::LayerHierarchy::Variant; - LayerProto* layerProto = mLayersProto.add_layers(); + perfetto::protos::LayerProto* layerProto = mLayersProto.add_layers(); const frontend::RequestedLayerState& layer = *root.getLayer(); frontend::LayerSnapshot* snapshot = getSnapshot(path, layer); LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags); @@ -349,7 +362,7 @@ void LayerProtoFromSnapshotGenerator::writeHierarchyToProto( } } -void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, +void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerInfo, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags) { @@ -446,9 +459,9 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, [&]() { return layerInfo->mutable_destination_frame(); }); } -google::protobuf::RepeatedPtrField LayerProtoHelper::writeDisplayInfoToProto( - const frontend::DisplayInfos& displayInfos) { - google::protobuf::RepeatedPtrField displays; +google::protobuf::RepeatedPtrField +LayerProtoHelper::writeDisplayInfoToProto(const frontend::DisplayInfos& displayInfos) { + google::protobuf::RepeatedPtrField displays; displays.Reserve(displayInfos.size()); for (const auto& [layerStack, displayInfo] : displayInfos) { auto displayProto = displays.Add(); diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 346685f259..20c226006c 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -35,39 +35,47 @@ namespace android { namespace surfaceflinger { class LayerProtoHelper { public: - static void writePositionToProto(const float x, const float y, - std::function getPositionProto); + static void writePositionToProto( + const float x, const float y, + std::function getPositionProto); static void writeSizeToProto(const uint32_t w, const uint32_t h, - std::function getSizeProto); - static void writeToProto(const Rect& rect, std::function getRectProto); - static void writeToProto(const Rect& rect, RectProto* rectProto); - static void readFromProto(const RectProto& proto, Rect& outRect); + std::function getSizeProto); + static void writeToProto(const Rect& rect, + std::function getRectProto); + static void writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto); + static void readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect); static void writeToProto(const FloatRect& rect, - std::function getFloatRectProto); - static void writeToProto(const Region& region, std::function getRegionProto); - static void writeToProto(const Region& region, RegionProto* regionProto); - static void readFromProto(const RegionProto& regionProto, Region& outRegion); - static void writeToProto(const half4 color, std::function getColorProto); + std::function getFloatRectProto); + static void writeToProto(const Region& region, + std::function getRegionProto); + static void writeToProto(const Region& region, perfetto::protos::RegionProto* regionProto); + static void readFromProto(const perfetto::protos::RegionProto& regionProto, Region& outRegion); + static void writeToProto(const half4 color, + std::function getColorProto); // This writeToProto for transform is incorrect, but due to backwards compatibility, we can't // update Layers to use it. Use writeTransformToProto for any new transform proto data. static void writeToProtoDeprecated(const ui::Transform& transform, - TransformProto* transformProto); + perfetto::protos::TransformProto* transformProto); static void writeTransformToProto(const ui::Transform& transform, - TransformProto* transformProto); - static void writeToProto(const renderengine::ExternalTexture& buffer, - std::function getActiveBufferProto); - static void writeToProto(const gui::WindowInfo& inputInfo, - const wp& touchableRegionBounds, - std::function getInputWindowInfoProto); - static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto); - static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix); - static void writeToProto(const android::BlurRegion region, BlurRegion*); - static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion); - static void writeSnapshotToProto(LayerProto* outProto, + perfetto::protos::TransformProto* transformProto); + static void writeToProto( + const renderengine::ExternalTexture& buffer, + std::function getActiveBufferProto); + static void writeToProto( + const gui::WindowInfo& inputInfo, const wp& touchableRegionBounds, + std::function getInputWindowInfoProto); + static void writeToProto(const mat4 matrix, + perfetto::protos::ColorTransformProto* colorTransformProto); + static void readFromProto(const perfetto::protos::ColorTransformProto& colorTransformProto, + mat4& matrix); + static void writeToProto(const android::BlurRegion region, perfetto::protos::BlurRegion*); + static void readFromProto(const perfetto::protos::BlurRegion& proto, + android::BlurRegion& outRegion); + static void writeSnapshotToProto(perfetto::protos::LayerProto* outProto, const frontend::RequestedLayerState& requestedState, const frontend::LayerSnapshot& snapshot, uint32_t traceFlags); - static google::protobuf::RepeatedPtrField writeDisplayInfoToProto( - const frontend::DisplayInfos&); + static google::protobuf::RepeatedPtrField + writeDisplayInfoToProto(const frontend::DisplayInfos&); }; class LayerProtoFromSnapshotGenerator { @@ -80,7 +88,7 @@ public: mLegacyLayers(legacyLayers), mDisplayInfos(displayInfos), mTraceFlags(traceFlags) {} - LayersProto generate(const frontend::LayerHierarchy& root); + perfetto::protos::LayersProto generate(const frontend::LayerHierarchy& root); private: void writeHierarchyToProto(const frontend::LayerHierarchy& root, @@ -92,7 +100,7 @@ private: const std::unordered_map>& mLegacyLayers; const frontend::DisplayInfos& mDisplayInfos; uint32_t mTraceFlags; - LayersProto mLayersProto; + perfetto::protos::LayersProto mLayersProto; // winscope expects all the layers, so provide a snapshot even if it not currently drawing std::unordered_map diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bc626f3030..e24c0dba4d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5889,9 +5889,10 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { } if (dumpLayers) { - LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto(); - LayersTraceProto* layersTrace = traceFileProto.add_entry(); - LayersProto layersProto = dumpProtoFromMainThread(); + perfetto::protos::LayersTraceFileProto traceFileProto = + mLayerTracing.createTraceFileProto(); + perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry(); + perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread(); layersTrace->mutable_layers()->Swap(&layersProto); auto displayProtos = dumpDisplayProto(); layersTrace->mutable_displays()->Swap(&displayProtos); @@ -6117,7 +6118,7 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } -LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { +perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { std::unordered_set stackIdsToSkip; // Determine if virtual layers display should be skipped @@ -6130,7 +6131,7 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } if (mLegacyFrontEndEnabled) { - LayersProto layersProto; + perfetto::protos::LayersProto layersProto; for (const sp& layer : mDrawingState.layersSortedByZ) { if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { continue; @@ -6145,10 +6146,11 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { .generate(mLayerHierarchyBuilder.getHierarchy()); } -google::protobuf::RepeatedPtrField SurfaceFlinger::dumpDisplayProto() const { - google::protobuf::RepeatedPtrField displays; +google::protobuf::RepeatedPtrField +SurfaceFlinger::dumpDisplayProto() const { + google::protobuf::RepeatedPtrField displays; for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { - DisplayProto* displayProto = displays.Add(); + perfetto::protos::DisplayProto* displayProto = displays.Add(); displayProto->set_id(display->getId().value); displayProto->set_name(display->getDisplayName()); displayProto->set_layer_stack(display->getLayerStack().id); @@ -6175,10 +6177,11 @@ void SurfaceFlinger::dumpHwc(std::string& result) const { getHwComposer().dump(result); } -void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const { +void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, + uint32_t traceFlags) const { // Add a fake invisible root layer to the proto output and parent all the offscreen layers to // it. - LayerProto* rootProto = layersProto.add_layers(); + perfetto::protos::LayerProto* rootProto = layersProto.add_layers(); const int32_t offscreenRootLayerId = INT32_MAX - 2; rootProto->set_id(offscreenRootLayerId); rootProto->set_name("Offscreen Root"); @@ -6189,12 +6192,12 @@ void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t rootProto->add_children(offscreenLayer->sequence); // Add layer - LayerProto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); + auto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); layerProto->set_parent(offscreenRootLayerId); } } -LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { +perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { return mScheduler->schedule([=] { return dumpDrawingStateProto(traceFlags); }).get(); } @@ -8790,7 +8793,7 @@ frontend::Update SurfaceFlinger::flushLifecycleUpdates() { void SurfaceFlinger::addToLayerTracing(bool visibleRegionDirty, TimePoint time, VsyncId vsyncId) { const uint32_t tracingFlags = mLayerTracing.getFlags(); - LayersProto layers(dumpDrawingStateProto(tracingFlags)); + perfetto::protos::LayersProto layers(dumpDrawingStateProto(tracingFlags)); if (tracingFlags & LayerTracing::TRACE_EXTRA) { dumpOffscreenLayersProto(layers); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 79dcd0d1b2..693bf3b35a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1092,17 +1092,17 @@ private: void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); - LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; - void dumpOffscreenLayersProto(LayersProto& layersProto, + perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; + void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, uint32_t traceFlags = LayerTracing::TRACE_ALL) const; - google::protobuf::RepeatedPtrField dumpDisplayProto() const; + google::protobuf::RepeatedPtrField dumpDisplayProto() const; void addToLayerTracing(bool visibleRegionDirty, TimePoint, VsyncId) REQUIRES(kMainThreadContext); // Dumps state from HW Composer void dumpHwc(std::string& result) const; - LayersProto dumpProtoFromMainThread(uint32_t traceFlags = LayerTracing::TRACE_ALL) - EXCLUDES(mStateLock); + perfetto::protos::LayersProto dumpProtoFromMainThread( + uint32_t traceFlags = LayerTracing::TRACE_ALL) EXCLUDES(mStateLock); void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock); void dumpPlannerInfo(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index b1e3d6378a..2dc89b55ba 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -51,8 +51,8 @@ public: ~FakeExternalTexture() = default; }; -proto::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { - proto::TransactionState proto; +perfetto::protos::TransactionState TransactionProtoParser::toProto(const TransactionState& t) { + perfetto::protos::TransactionState proto; proto.set_pid(t.originPid); proto.set_uid(t.originUid); proto.set_vsync_id(t.frameTimelineInfo.vsyncId); @@ -79,21 +79,21 @@ proto::TransactionState TransactionProtoParser::toProto(const TransactionState& return proto; } -proto::TransactionState TransactionProtoParser::toProto( +perfetto::protos::TransactionState TransactionProtoParser::toProto( const std::map& states) { - proto::TransactionState proto; + perfetto::protos::TransactionState proto; proto.mutable_layer_changes()->Reserve(static_cast(states.size())); for (auto& [layerId, state] : states) { - proto::LayerState layerProto = toProto(state); + perfetto::protos::LayerState layerProto = toProto(state); layerProto.set_has_sideband_stream(state.hasSidebandStream); proto.mutable_layer_changes()->Add(std::move(layerProto)); } return proto; } -proto::LayerState TransactionProtoParser::toProto( +perfetto::protos::LayerState TransactionProtoParser::toProto( const ResolvedComposerState& resolvedComposerState) { - proto::LayerState proto; + perfetto::protos::LayerState proto; auto& layer = resolvedComposerState.state; proto.set_layer_id(resolvedComposerState.layerId); proto.set_what(layer.what); @@ -114,7 +114,7 @@ proto::LayerState TransactionProtoParser::toProto( proto.set_mask(layer.mask); } if (layer.what & layer_state_t::eMatrixChanged) { - proto::LayerState_Matrix22* matrixProto = proto.mutable_matrix(); + perfetto::protos::LayerState_Matrix22* matrixProto = proto.mutable_matrix(); matrixProto->set_dsdx(layer.matrix.dsdx); matrixProto->set_dsdy(layer.matrix.dsdy); matrixProto->set_dtdx(layer.matrix.dtdx); @@ -132,7 +132,7 @@ proto::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eColorChanged) { - proto::LayerState_Color3* colorProto = proto.mutable_color(); + perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color(); colorProto->set_r(layer.color.r); colorProto->set_g(layer.color.g); colorProto->set_b(layer.color.b); @@ -150,13 +150,14 @@ proto::LayerState TransactionProtoParser::toProto( LayerProtoHelper::writeToProto(layer.crop, proto.mutable_crop()); } if (layer.what & layer_state_t::eBufferChanged) { - proto::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); + perfetto::protos::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); if (resolvedComposerState.externalTexture) { bufferProto->set_buffer_id(resolvedComposerState.externalTexture->getId()); bufferProto->set_width(resolvedComposerState.externalTexture->getWidth()); bufferProto->set_height(resolvedComposerState.externalTexture->getHeight()); - bufferProto->set_pixel_format(static_cast( - resolvedComposerState.externalTexture->getPixelFormat())); + bufferProto->set_pixel_format( + static_cast( + resolvedComposerState.externalTexture->getPixelFormat())); bufferProto->set_usage(resolvedComposerState.externalTexture->getUsage()); } bufferProto->set_frame_number(layer.bufferData->frameNumber); @@ -191,7 +192,8 @@ proto::LayerState TransactionProtoParser::toProto( if (layer.what & layer_state_t::eInputInfoChanged) { if (layer.windowInfoHandle) { const gui::WindowInfo* inputInfo = layer.windowInfoHandle->getInfo(); - proto::LayerState_WindowInfo* windowInfoProto = proto.mutable_window_info_handle(); + perfetto::protos::LayerState_WindowInfo* windowInfoProto = + proto.mutable_window_info_handle(); windowInfoProto->set_layout_params_flags(inputInfo->layoutParamsFlags.get()); windowInfoProto->set_layout_params_type( static_cast(inputInfo->layoutParamsType)); @@ -204,7 +206,7 @@ proto::LayerState TransactionProtoParser::toProto( windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test( gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)); windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor); - proto::Transform* transformProto = windowInfoProto->mutable_transform(); + perfetto::protos::Transform* transformProto = windowInfoProto->mutable_transform(); transformProto->set_dsdx(inputInfo->transform.dsdx()); transformProto->set_dtdx(inputInfo->transform.dtdx()); transformProto->set_dtdy(inputInfo->transform.dtdy()); @@ -219,7 +221,7 @@ proto::LayerState TransactionProtoParser::toProto( if (layer.what & layer_state_t::eBackgroundColorChanged) { proto.set_bg_color_alpha(layer.bgColor.a); proto.set_bg_color_dataspace(static_cast(layer.bgColorDataspace)); - proto::LayerState_Color3* colorProto = proto.mutable_color(); + perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color(); colorProto->set_r(layer.bgColor.r); colorProto->set_g(layer.bgColor.g); colorProto->set_b(layer.bgColor.b); @@ -255,13 +257,13 @@ proto::LayerState TransactionProtoParser::toProto( } if (layer.what & layer_state_t::eDropInputModeChanged) { proto.set_drop_input_mode( - static_cast(layer.dropInputMode)); + static_cast(layer.dropInputMode)); } return proto; } -proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) { - proto::DisplayState proto; +perfetto::protos::DisplayState TransactionProtoParser::toProto(const DisplayState& display) { + perfetto::protos::DisplayState proto; proto.set_what(display.what); proto.set_id(mMapper->getDisplayId(display.token)); @@ -285,8 +287,8 @@ proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) return proto; } -proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) { - proto::LayerCreationArgs proto; +perfetto::protos::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) { + perfetto::protos::LayerCreationArgs proto; proto.set_layer_id(args.sequence); proto.set_name(args.name); proto.set_flags(args.flags); @@ -297,7 +299,8 @@ proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs return proto; } -TransactionState TransactionProtoParser::fromProto(const proto::TransactionState& proto) { +TransactionState TransactionProtoParser::fromProto( + const perfetto::protos::TransactionState& proto) { TransactionState t; t.originPid = proto.pid(); t.originUid = proto.uid(); @@ -323,7 +326,7 @@ TransactionState TransactionProtoParser::fromProto(const proto::TransactionState return t; } -void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto, +void TransactionProtoParser::fromProto(const perfetto::protos::LayerCreationArgs& proto, LayerCreationArgs& outArgs) { outArgs.sequence = proto.layer_id(); @@ -335,7 +338,7 @@ void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto, outArgs.layerStackToMirror.id = proto.layer_stack_to_mirror(); } -void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto, +void TransactionProtoParser::mergeFromProto(const perfetto::protos::LayerState& proto, TracingLayerState& outState) { ResolvedComposerState resolvedComposerState; fromProto(proto, resolvedComposerState); @@ -360,7 +363,7 @@ void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto, } } -void TransactionProtoParser::fromProto(const proto::LayerState& proto, +void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto, ResolvedComposerState& resolvedComposerState) { auto& layer = resolvedComposerState.state; resolvedComposerState.layerId = proto.layer_id(); @@ -381,7 +384,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer.mask = proto.mask(); } if (proto.what() & layer_state_t::eMatrixChanged) { - const proto::LayerState_Matrix22& matrixProto = proto.matrix(); + const perfetto::protos::LayerState_Matrix22& matrixProto = proto.matrix(); layer.matrix.dsdx = matrixProto.dsdx(); layer.matrix.dsdy = matrixProto.dsdy(); layer.matrix.dtdx = matrixProto.dtdx(); @@ -399,7 +402,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, } if (proto.what() & layer_state_t::eColorChanged) { - const proto::LayerState_Color3& colorProto = proto.color(); + const perfetto::protos::LayerState_Color3& colorProto = proto.color(); layer.color.r = colorProto.r(); layer.color.g = colorProto.g(); layer.color.b = colorProto.b(); @@ -417,7 +420,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, LayerProtoHelper::readFromProto(proto.crop(), layer.crop); } if (proto.what() & layer_state_t::eBufferChanged) { - const proto::LayerState_BufferData& bufferProto = proto.buffer_data(); + const perfetto::protos::LayerState_BufferData& bufferProto = proto.buffer_data(); layer.bufferData = std::make_shared(bufferProto.buffer_id(), bufferProto.width(), bufferProto.height(), bufferProto.pixel_format(), @@ -460,7 +463,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, if ((proto.what() & layer_state_t::eInputInfoChanged) && proto.has_window_info_handle()) { gui::WindowInfo inputInfo; - const proto::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle(); + const perfetto::protos::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle(); inputInfo.layoutParamsFlags = static_cast(windowInfoProto.layout_params_flags()); @@ -472,7 +475,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, ftl::Flags(windowInfoProto.input_config()); inputInfo.surfaceInset = windowInfoProto.surface_inset(); inputInfo.globalScaleFactor = windowInfoProto.global_scale_factor(); - const proto::Transform& transformProto = windowInfoProto.transform(); + const perfetto::protos::Transform& transformProto = windowInfoProto.transform(); inputInfo.transform.set(transformProto.dsdx(), transformProto.dtdx(), transformProto.dtdy(), transformProto.dsdy()); inputInfo.transform.set(transformProto.tx(), transformProto.ty()); @@ -485,7 +488,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, if (proto.what() & layer_state_t::eBackgroundColorChanged) { layer.bgColor.a = proto.bg_color_alpha(); layer.bgColorDataspace = static_cast(proto.bg_color_dataspace()); - const proto::LayerState_Color3& colorProto = proto.color(); + const perfetto::protos::LayerState_Color3& colorProto = proto.color(); layer.bgColor.r = colorProto.r(); layer.bgColor.g = colorProto.g(); layer.bgColor.b = colorProto.b(); @@ -525,7 +528,7 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, } } -DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) { +DisplayState TransactionProtoParser::fromProto(const perfetto::protos::DisplayState& proto) { DisplayState display; display.what = proto.what(); display.token = mMapper->getDisplayHandle(proto.id()); @@ -550,7 +553,7 @@ DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) return display; } -void asProto(proto::Transform* proto, const ui::Transform& transform) { +void asProto(perfetto::protos::Transform* proto, const ui::Transform& transform) { proto->set_dsdx(transform.dsdx()); proto->set_dtdx(transform.dtdx()); proto->set_dtdy(transform.dtdy()); @@ -559,9 +562,9 @@ void asProto(proto::Transform* proto, const ui::Transform& transform) { proto->set_ty(transform.ty()); } -proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& displayInfo, - uint32_t layerStack) { - proto::DisplayInfo proto; +perfetto::protos::DisplayInfo TransactionProtoParser::toProto( + const frontend::DisplayInfo& displayInfo, uint32_t layerStack) { + perfetto::protos::DisplayInfo proto; proto.set_layer_stack(layerStack); proto.set_display_id(displayInfo.info.displayId); proto.set_logical_width(displayInfo.info.logicalWidth); @@ -577,12 +580,13 @@ proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& return proto; } -void fromProto2(ui::Transform& outTransform, const proto::Transform& proto) { +void fromProto2(ui::Transform& outTransform, const perfetto::protos::Transform& proto) { outTransform.set(proto.dsdx(), proto.dtdx(), proto.dtdy(), proto.dsdy()); outTransform.set(proto.tx(), proto.ty()); } -frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo& proto) { +frontend::DisplayInfo TransactionProtoParser::fromProto( + const perfetto::protos::DisplayInfo& proto) { frontend::DisplayInfo displayInfo; displayInfo.info.displayId = proto.display_id(); displayInfo.info.logicalWidth = proto.logical_width(); @@ -599,10 +603,10 @@ frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo } void TransactionProtoParser::fromProto( - const google::protobuf::RepeatedPtrField& proto, + const google::protobuf::RepeatedPtrField& proto, frontend::DisplayInfos& outDisplayInfos) { outDisplayInfos.clear(); - for (const proto::DisplayInfo& displayInfo : proto) { + for (const perfetto::protos::DisplayInfo& displayInfo : proto) { outDisplayInfos.emplace_or_replace(ui::LayerStack::fromValue(displayInfo.layer_stack()), fromProto(displayInfo)); } diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h index 457c3bec40..b3ab71cfb5 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.h +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h @@ -44,25 +44,25 @@ public: TransactionProtoParser(std::unique_ptr provider) : mMapper(std::move(provider)) {} - proto::TransactionState toProto(const TransactionState&); - proto::TransactionState toProto(const std::map&); - proto::LayerCreationArgs toProto(const LayerCreationArgs& args); - proto::LayerState toProto(const ResolvedComposerState&); - static proto::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); + perfetto::protos::TransactionState toProto(const TransactionState&); + perfetto::protos::TransactionState toProto( + const std::map&); + perfetto::protos::LayerCreationArgs toProto(const LayerCreationArgs& args); + perfetto::protos::LayerState toProto(const ResolvedComposerState&); + static perfetto::protos::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack); - TransactionState fromProto(const proto::TransactionState&); - void mergeFromProto(const proto::LayerState&, TracingLayerState& outState); - void fromProto(const proto::LayerCreationArgs&, LayerCreationArgs& outArgs); + TransactionState fromProto(const perfetto::protos::TransactionState&); + void mergeFromProto(const perfetto::protos::LayerState&, TracingLayerState& outState); + void fromProto(const perfetto::protos::LayerCreationArgs&, LayerCreationArgs& outArgs); std::unique_ptr mMapper; - static frontend::DisplayInfo fromProto(const proto::DisplayInfo&); - static void fromProto(const google::protobuf::RepeatedPtrField&, + static frontend::DisplayInfo fromProto(const perfetto::protos::DisplayInfo&); + static void fromProto(const google::protobuf::RepeatedPtrField&, frontend::DisplayInfos& outDisplayInfos); private: - proto::DisplayState toProto(const DisplayState&); - void fromProto(const proto::LayerState&, ResolvedComposerState& out); - DisplayState fromProto(const proto::DisplayState&); - + perfetto::protos::DisplayState toProto(const DisplayState&); + void fromProto(const perfetto::protos::LayerState&, ResolvedComposerState& out); + DisplayState fromProto(const perfetto::protos::DisplayState&); }; } // namespace android::surfaceflinger diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp index bc69191cc1..8aacbca90c 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.cpp +++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp @@ -59,7 +59,7 @@ TransactionTracing::~TransactionTracing() { status_t TransactionTracing::writeToFile(const std::string& filename) { std::scoped_lock lock(mTraceLock); - proto::TransactionTraceFile fileProto = createTraceFileProto(); + perfetto::protos::TransactionTraceFile fileProto = createTraceFileProto(); addStartingStateToProtoLocked(fileProto); return mBuffer.writeToFile(fileProto, filename); } @@ -70,10 +70,11 @@ void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) { mBuffer.setSize(mBufferSizeInBytes); } -proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { - proto::TransactionTraceFile proto; - proto.set_magic_number(uint64_t(proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 | - proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L); +perfetto::protos::TransactionTraceFile TransactionTracing::createTraceFileProto() const { + perfetto::protos::TransactionTraceFile proto; + proto.set_magic_number( + uint64_t(perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 | + perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L); auto timeOffsetNs = static_cast(systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC)); proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs); @@ -89,7 +90,8 @@ void TransactionTracing::dump(std::string& result) const { } void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) { - proto::TransactionState* state = new proto::TransactionState(mProtoParser.toProto(transaction)); + perfetto::protos::TransactionState* state = + new perfetto::protos::TransactionState(mProtoParser.toProto(transaction)); mTransactionQueue.push(state); } @@ -152,7 +154,7 @@ void TransactionTracing::addEntry(const std::vector& committed ATRACE_CALL(); std::scoped_lock lock(mTraceLock); std::vector removedEntries; - proto::TransactionTraceEntry entryProto; + perfetto::protos::TransactionTraceEntry entryProto; while (auto incomingTransaction = mTransactionQueue.pop()) { auto transaction = *incomingTransaction; @@ -211,7 +213,7 @@ void TransactionTracing::addEntry(const std::vector& committed std::make_move_iterator(entries.end())); } - proto::TransactionTraceEntry removedEntryProto; + perfetto::protos::TransactionTraceEntry removedEntryProto; for (const std::string& removedEntry : removedEntries) { removedEntryProto.ParseFromString(removedEntry); updateStartingStateLocked(removedEntryProto); @@ -236,7 +238,7 @@ void TransactionTracing::flush() { base::ScopedLockAssertion assumeLocked(mTraceLock); mTransactionsAddedToBufferCv.wait_for(lock, std::chrono::milliseconds(100), [&]() REQUIRES(mTraceLock) { - proto::TransactionTraceEntry entry; + perfetto::protos::TransactionTraceEntry entry; if (mBuffer.used() > 0) { entry.ParseFromString(mBuffer.back()); } @@ -268,19 +270,19 @@ void TransactionTracing::tryPushToTracingThread() { } void TransactionTracing::updateStartingStateLocked( - const proto::TransactionTraceEntry& removedEntry) { + const perfetto::protos::TransactionTraceEntry& removedEntry) { mStartingTimestamp = removedEntry.elapsed_realtime_nanos(); // Keep track of layer starting state so we can reconstruct the layer state as we purge // transactions from the buffer. - for (const proto::LayerCreationArgs& addedLayer : removedEntry.added_layers()) { + for (const perfetto::protos::LayerCreationArgs& addedLayer : removedEntry.added_layers()) { TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()]; startingState.layerId = addedLayer.layer_id(); mProtoParser.fromProto(addedLayer, startingState.args); } // Merge layer states to starting transaction state. - for (const proto::TransactionState& transaction : removedEntry.transactions()) { - for (const proto::LayerState& layerState : transaction.layer_changes()) { + for (const perfetto::protos::TransactionState& transaction : removedEntry.transactions()) { + for (const perfetto::protos::LayerState& layerState : transaction.layer_changes()) { auto it = mStartingStates.find(layerState.layer_id()); if (it == mStartingStates.end()) { // TODO(b/238781169) make this log fatal when we switch over to using new fe @@ -307,12 +309,13 @@ void TransactionTracing::updateStartingStateLocked( } } -void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) { +void TransactionTracing::addStartingStateToProtoLocked( + perfetto::protos::TransactionTraceFile& proto) { if (mStartingStates.size() == 0) { return; } - proto::TransactionTraceEntry* entryProto = proto.add_entry(); + perfetto::protos::TransactionTraceEntry* entryProto = proto.add_entry(); entryProto->set_elapsed_realtime_nanos(mStartingTimestamp); entryProto->set_vsync_id(0); @@ -321,7 +324,7 @@ void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFi entryProto->mutable_added_layers()->Add(mProtoParser.toProto(state.args)); } - proto::TransactionState transactionProto = mProtoParser.toProto(mStartingStates); + perfetto::protos::TransactionState transactionProto = mProtoParser.toProto(mStartingStates); transactionProto.set_vsync_id(0); transactionProto.set_post_time(mStartingTimestamp); entryProto->mutable_transactions()->Add(std::move(transactionProto)); @@ -338,9 +341,9 @@ void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFi } } -proto::TransactionTraceFile TransactionTracing::writeToProto() { +perfetto::protos::TransactionTraceFile TransactionTracing::writeToProto() { std::scoped_lock lock(mTraceLock); - proto::TransactionTraceFile proto = createTraceFileProto(); + perfetto::protos::TransactionTraceFile proto = createTraceFileProto(); addStartingStateToProtoLocked(proto); mBuffer.writeToProto(proto); return proto; diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h index 422b5f3689..09fcd8ad96 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.h +++ b/services/surfaceflinger/Tracing/TransactionTracing.h @@ -85,14 +85,16 @@ private: } mutable std::mutex mTraceLock; - TransactionRingBuffer mBuffer - GUARDED_BY(mTraceLock); + TransactionRingBuffer + mBuffer GUARDED_BY(mTraceLock); size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; - std::unordered_map mQueuedTransactions + std::unordered_map mQueuedTransactions GUARDED_BY(mTraceLock); - LocklessStack mTransactionQueue; + LocklessStack mTransactionQueue; nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock); - std::unordered_map mCreatedLayers GUARDED_BY(mTraceLock); + std::unordered_map mCreatedLayers + GUARDED_BY(mTraceLock); std::map mStartingStates GUARDED_BY(mTraceLock); frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock); @@ -122,17 +124,19 @@ private: std::vector mPendingDestroyedLayers; // only accessed by main thread int64_t mLastUpdatedVsyncId = -1; - proto::TransactionTraceFile createTraceFileProto() const; + perfetto::protos::TransactionTraceFile createTraceFileProto() const; void loop(); void addEntry(const std::vector& committedTransactions, const std::vector& removedLayers) EXCLUDES(mTraceLock); int32_t getLayerIdLocked(const sp& layerHandle) REQUIRES(mTraceLock); void tryPushToTracingThread() EXCLUDES(mMainThreadLock); - void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock); - void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock); + void addStartingStateToProtoLocked(perfetto::protos::TransactionTraceFile& proto) + REQUIRES(mTraceLock); + void updateStartingStateLocked(const perfetto::protos::TransactionTraceEntry& entry) + REQUIRES(mTraceLock); // TEST // Return buffer contents as trace file proto - proto::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); + perfetto::protos::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock); }; class TransactionTraceWriter : public Singleton { diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 321b8baccc..9471e954d8 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -40,8 +40,8 @@ namespace android { using namespace ftl::flag_operators; -bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, - const char* outputLayersTracePath, bool onlyLastEntry) { +bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& traceFile, + const char*, bool onlyLastEntry) { if (traceFile.entry_size() == 0) { ALOGD("Trace file is empty"); return false; diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h index e41d1e6e0b..a1e5fc894b 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h @@ -21,7 +21,7 @@ namespace android { class LayerTraceGenerator { public: - bool generate(const proto::TransactionTraceFile&, const char* outputLayersTracePath, + bool generate(const perfetto::protos::TransactionTraceFile&, const char* outputLayersTracePath, bool onlyLastEntry); }; -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp index 5ca87e4cb3..0ff8f98d36 100644 --- a/services/surfaceflinger/Tracing/tools/main.cpp +++ b/services/surfaceflinger/Tracing/tools/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) { return -1; } - proto::TransactionTraceFile transactionTraceFile; + perfetto::protos::TransactionTraceFile transactionTraceFile; if (!transactionTraceFile.ParseFromIstream(&input)) { std::cout << "Error: Failed to parse " << transactionTracePath; return -1; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 8a050fdab5..437fd35c15 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -455,7 +455,8 @@ public: result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result); - LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); + perfetto::protos::LayersProto layersProto = + mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); mFlinger->dumpOffscreenLayersProto(layersProto); mFlinger->dumpDisplayProto(); diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index 7287dd0103..a4dc8a058e 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -13,7 +13,20 @@ cc_library { srcs: [ "LayerProtoParser.cpp", - "*.proto", + ], + + static_libs: [ + "libperfetto_client_experimental", + ], + + whole_static_libs: [ + // TODO(b/169779783): move into "static_libs" when the soong issue is fixed + "perfetto_trace_protos", + ], + + export_static_lib_headers: [ + "libperfetto_client_experimental", + "perfetto_trace_protos", ], shared_libs: [ @@ -24,10 +37,6 @@ cc_library { "libbase", ], - proto: { - export_proto_headers: true, - }, - cppflags: [ "-Werror", "-Wno-unused-parameter", @@ -42,22 +51,3 @@ cc_library { "-Wno-undef", ], } - -java_library_static { - name: "layersprotoslite", - host_supported: true, - proto: { - type: "lite", - include_dirs: ["external/protobuf/src"], - }, - srcs: ["*.proto"], - sdk_version: "core_platform", - target: { - android: { - jarjar_rules: "jarjar-rules.txt", - }, - host: { - static_libs: ["libprotobuf-java-lite"], - }, - }, -} diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 854084e7f9..8d48070e13 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -37,7 +37,8 @@ bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs return lhs->id < rhs->id; } -LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProto& layersProto) { +LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree( + const perfetto::protos::LayersProto& layersProto) { LayerTree layerTree; layerTree.allLayers = generateLayerList(layersProto); @@ -53,7 +54,7 @@ LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProt } std::vector LayerProtoParser::generateLayerList( - const LayersProto& layersProto) { + const perfetto::protos::LayersProto& layersProto) { std::vector layerList; std::unordered_map layerMap; @@ -74,7 +75,8 @@ std::vector LayerProtoParser::generateLayerList( return layerList; } -LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerProto) { +LayerProtoParser::Layer LayerProtoParser::generateLayer( + const perfetto::protos::LayerProto& layerProto) { Layer layer; layer.id = layerProto.id(); layer.name = layerProto.name(); @@ -120,17 +122,19 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP return layer; } -LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) { +LayerProtoParser::Region LayerProtoParser::generateRegion( + const perfetto::protos::RegionProto& regionProto) { LayerProtoParser::Region region; for (int i = 0; i < regionProto.rect_size(); i++) { - const RectProto& rectProto = regionProto.rect(i); + const perfetto::protos::RectProto& rectProto = regionProto.rect(i); region.rects.push_back(generateRect(rectProto)); } return region; } -LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) { +LayerProtoParser::Rect LayerProtoParser::generateRect( + const perfetto::protos::RectProto& rectProto) { LayerProtoParser::Rect rect; rect.left = rectProto.left(); rect.top = rectProto.top(); @@ -140,7 +144,8 @@ LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto return rect; } -LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) { +LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect( + const perfetto::protos::FloatRectProto& rectProto) { LayerProtoParser::FloatRect rect; rect.left = rectProto.left(); rect.top = rectProto.top(); @@ -151,7 +156,7 @@ LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectP } LayerProtoParser::Transform LayerProtoParser::generateTransform( - const TransformProto& transformProto) { + const perfetto::protos::TransformProto& transformProto) { LayerProtoParser::Transform transform; transform.dsdx = transformProto.dsdx(); transform.dtdx = transformProto.dtdx(); @@ -162,7 +167,7 @@ LayerProtoParser::Transform LayerProtoParser::generateTransform( } LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( - const ActiveBufferProto& activeBufferProto) { + const perfetto::protos::ActiveBufferProto& activeBufferProto) { LayerProtoParser::ActiveBuffer activeBuffer; activeBuffer.width = activeBufferProto.width(); activeBuffer.height = activeBufferProto.height(); @@ -172,7 +177,7 @@ LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( return activeBuffer; } -void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, +void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto, std::unordered_map& layerMap) { auto currLayer = layerMap[layerProto.id()]; diff --git a/services/surfaceflinger/layerproto/common.proto b/services/surfaceflinger/layerproto/common.proto deleted file mode 100644 index 5e20d4d0f5..0000000000 --- a/services/surfaceflinger/layerproto/common.proto +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; -package android.surfaceflinger; - -message RegionProto { - reserved 1; // Previously: uint64 id - repeated RectProto rect = 2; -} - -message RectProto { - int32 left = 1; - int32 top = 2; - int32 right = 3; - int32 bottom = 4; -} - -message SizeProto { - int32 w = 1; - int32 h = 2; -} - -message TransformProto { - float dsdx = 1; - float dtdx = 2; - float dsdy = 3; - float dtdy = 4; - int32 type = 5; -} - -message ColorProto { - float r = 1; - float g = 2; - float b = 3; - float a = 4; -} - -message InputWindowInfoProto { - uint32 layout_params_flags = 1; - int32 layout_params_type = 2; - RectProto frame = 3; - RegionProto touchable_region = 4; - - int32 surface_inset = 5; - bool visible = 6; - bool can_receive_keys = 7 [deprecated = true]; - bool focusable = 8; - bool has_wallpaper = 9; - - float global_scale_factor = 10; - float window_x_scale = 11 [deprecated = true]; - float window_y_scale = 12 [deprecated = true]; - - int32 crop_layer_id = 13; - bool replace_touchable_region_with_crop = 14; - RectProto touchable_region_crop = 15; - TransformProto transform = 16; - uint32 input_config = 17; -} - -message BlurRegion { - uint32 blur_radius = 1; - uint32 corner_radius_tl = 2; - uint32 corner_radius_tr = 3; - uint32 corner_radius_bl = 4; - float corner_radius_br = 5; - float alpha = 6; - int32 left = 7; - int32 top = 8; - int32 right = 9; - int32 bottom = 10; -} - -message ColorTransformProto { - // This will be a 4x4 matrix of float values - repeated float val = 1; -} diff --git a/services/surfaceflinger/layerproto/display.proto b/services/surfaceflinger/layerproto/display.proto deleted file mode 100644 index 64de775b8b..0000000000 --- a/services/surfaceflinger/layerproto/display.proto +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; - -package android.surfaceflinger; - -message DisplayProto { - uint64 id = 1; - - string name = 2; - - uint32 layer_stack = 3; - - SizeProto size = 4; - - RectProto layer_stack_space_rect = 5; - - TransformProto transform = 6; - - bool is_virtual = 7; - - double dpi_x = 8; - - double dpi_y = 9; -} diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h index f560562c94..4a2ef3ddf8 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h @@ -14,11 +14,14 @@ * limitations under the License. */ +#pragma once + // pragma is used here to disable the warnings emitted from the protobuf // headers. By adding #pragma before including layer.pb.h, it supresses // protobuf warnings, but allows the rest of the files to continuing using // the current flags. // This file should be included instead of directly including layer.b.h #pragma GCC system_header -#include -#include +#include +#include +#include diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index cdc2706ee2..79c3982dbd 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -131,19 +131,22 @@ public: std::vector topLevelLayers; }; - static LayerTree generateLayerTree(const LayersProto& layersProto); + static LayerTree generateLayerTree(const perfetto::protos::LayersProto& layersProto); static std::string layerTreeToString(const LayerTree& layerTree); private: - static std::vector generateLayerList(const LayersProto& layersProto); - static LayerProtoParser::Layer generateLayer(const LayerProto& layerProto); - static LayerProtoParser::Region generateRegion(const RegionProto& regionProto); - static LayerProtoParser::Rect generateRect(const RectProto& rectProto); - static LayerProtoParser::FloatRect generateFloatRect(const FloatRectProto& rectProto); - static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto); + static std::vector generateLayerList(const perfetto::protos::LayersProto& layersProto); + static LayerProtoParser::Layer generateLayer(const perfetto::protos::LayerProto& layerProto); + static LayerProtoParser::Region generateRegion( + const perfetto::protos::RegionProto& regionProto); + static LayerProtoParser::Rect generateRect(const perfetto::protos::RectProto& rectProto); + static LayerProtoParser::FloatRect generateFloatRect( + const perfetto::protos::FloatRectProto& rectProto); + static LayerProtoParser::Transform generateTransform( + const perfetto::protos::TransformProto& transformProto); static LayerProtoParser::ActiveBuffer generateActiveBuffer( - const ActiveBufferProto& activeBufferProto); - static void updateChildrenAndRelative(const LayerProto& layerProto, + const perfetto::protos::ActiveBufferProto& activeBufferProto); + static void updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto, std::unordered_map& layerMap); static std::string layerToString(const LayerProtoParser::Layer* layer); diff --git a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h index 3e9ca52fff..ea80ad8f33 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h +++ b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h @@ -14,7 +14,11 @@ * limitations under the License. */ +#pragma once + // disable the warnings emitted from the protobuf headers. This file should be included instead of // directly including the generated header file #pragma GCC system_header -#include +#include +#include +#include diff --git a/services/surfaceflinger/layerproto/jarjar-rules.txt b/services/surfaceflinger/layerproto/jarjar-rules.txt deleted file mode 100644 index 40043a861c..0000000000 --- a/services/surfaceflinger/layerproto/jarjar-rules.txt +++ /dev/null @@ -1 +0,0 @@ -rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto deleted file mode 100644 index e9add2e1a4..0000000000 --- a/services/surfaceflinger/layerproto/layers.proto +++ /dev/null @@ -1,171 +0,0 @@ -// Definitions for SurfaceFlinger layers. - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; - -package android.surfaceflinger; - -// Contains a list of all layers. -message LayersProto { - repeated LayerProto layers = 1; -} - -// Must match definition in the IComposerClient HAL -enum HwcCompositionType { - // Invalid composition type - INVALID = 0; - // Layer was composited by the client into the client target buffer - CLIENT = 1; - // Layer was composited by the device through hardware overlays - DEVICE = 2; - // Layer was composited by the device using a color - SOLID_COLOR = 3; - // Similar to DEVICE, but the layer position may have been asynchronously set - // through setCursorPosition - CURSOR = 4; - // Layer was composited by the device via a sideband stream. - SIDEBAND = 5; -} - -// Information about each layer. -message LayerProto { - // unique id per layer. - int32 id = 1; - // unique name per layer. - string name = 2; - // list of children this layer may have. May be empty. - repeated int32 children = 3; - // list of layers that are z order relative to this layer. - repeated int32 relatives = 4; - // The type of layer, ex Color, Layer - string type = 5; - RegionProto transparent_region = 6; - RegionProto visible_region = 7; - RegionProto damage_region = 8; - uint32 layer_stack = 9; - // The layer's z order. Can be z order in layer stack, relative to parent, - // or relative to another layer specified in zOrderRelative. - int32 z = 10; - // The layer's position on the display. - PositionProto position = 11; - // The layer's requested position. - PositionProto requested_position = 12; - // The layer's size. - SizeProto size = 13; - // The layer's crop in it's own bounds. - RectProto crop = 14; - // The layer's crop in it's parent's bounds. - RectProto final_crop = 15 [deprecated=true]; - bool is_opaque = 16; - bool invalidate = 17; - string dataspace = 18; - string pixel_format = 19; - // The layer's actual color. - ColorProto color = 20; - // The layer's requested color. - ColorProto requested_color = 21; - // Can be any combination of - // hidden = 0x01 - // opaque = 0x02, - // secure = 0x80, - uint32 flags = 22; - // The layer's actual transform - TransformProto transform = 23; - // The layer's requested transform. - TransformProto requested_transform = 24; - // The parent layer. This value can be null if there is no parent. - int32 parent = 25; - // The layer that this layer has a z order relative to. This value can be null. - int32 z_order_relative_of = 26; - // This value can be null if there's nothing to draw. - ActiveBufferProto active_buffer = 27; - // The number of frames available. - int32 queued_frames = 28; - bool refresh_pending = 29; - // The layer's composer backend destination frame - RectProto hwc_frame = 30; - // The layer's composer backend source crop - FloatRectProto hwc_crop = 31; - // The layer's composer backend transform - int32 hwc_transform = 32; - int32 window_type = 33 [deprecated=true]; - int32 app_id = 34 [deprecated=true]; - // The layer's composition type - HwcCompositionType hwc_composition_type = 35; - // If it's a buffer layer, indicate if the content is protected - bool is_protected = 36; - // Current frame number being rendered. - uint64 curr_frame = 37; - // A list of barriers that the layer is waiting to update state. - repeated BarrierLayerProto barrier_layer = 38; - // If active_buffer is not null, record its transform. - TransformProto buffer_transform = 39; - int32 effective_scaling_mode = 40; - // Layer's corner radius. - float corner_radius = 41; - // Metadata map. May be empty. - map metadata = 42; - - TransformProto effective_transform = 43; - FloatRectProto source_bounds = 44; - FloatRectProto bounds = 45; - FloatRectProto screen_bounds = 46; - - InputWindowInfoProto input_window_info = 47; - - // Crop used to draw the rounded corner. - FloatRectProto corner_radius_crop = 48; - - // length of the shadow to draw around the layer, it may be set on the - // layer or set by a parent layer. - float shadow_radius = 49; - ColorTransformProto color_transform = 50; - - bool is_relative_of = 51; - // Layer's background blur radius in pixels. - int32 background_blur_radius = 52; - - uint32 owner_uid = 53; - - // Regions of a layer, where blur should be applied. - repeated BlurRegion blur_regions = 54; - - bool is_trusted_overlay = 55; - - // Corner radius explicitly set on layer rather than inherited - float requested_corner_radius = 56; - - RectProto destination_frame = 57; - - uint32 original_id = 58; -} - -message PositionProto { - float x = 1; - float y = 2; -} - -message FloatRectProto { - float left = 1; - float top = 2; - float right = 3; - float bottom = 4; -} - -message ActiveBufferProto { - uint32 width = 1; - uint32 height = 2; - uint32 stride = 3; - int32 format = 4; - uint64 usage = 5; -} - -message BarrierLayerProto { - // layer id the barrier is waiting on. - int32 id = 1; - // frame number the barrier is waiting on. - uint64 frame_number = 2; -} - diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto deleted file mode 100644 index 804a4994ee..0000000000 --- a/services/surfaceflinger/layerproto/layerstrace.proto +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/layers.proto"; -import "frameworks/native/services/surfaceflinger/layerproto/display.proto"; - -package android.surfaceflinger; - -/* represents a file full of surface flinger trace entries. - Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such - that they can be easily identified. */ -message LayersTraceFileProto { - - /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L - (this is needed because enums have to be 32 bits and there's no nice way to put 64bit - constants into .proto files. */ - enum MagicNumber { - INVALID = 0; - MAGIC_NUMBER_L = 0x5452594c; /* LYRT (little-endian ASCII) */ - MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ - } - - optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ - repeated LayersTraceProto entry = 2; - - /* offset between real-time clock and elapsed time clock in nanoseconds. - Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */ - optional fixed64 real_to_elapsed_time_offset_nanos = 3; -} - -/* one layers trace entry. */ -message LayersTraceProto { - /* required: elapsed realtime in nanos since boot of when this entry was logged */ - optional sfixed64 elapsed_realtime_nanos = 1; - - /* where the trace originated */ - optional string where = 2; - - optional LayersProto layers = 3; - - // Blob for the current HWC information for all layers, reported by dumpsys. - optional string hwc_blob = 4; - - /* Includes state sent during composition like visible region and composition type. */ - optional bool excludes_composition_state = 5; - - /* Number of missed entries since the last entry was recorded. */ - optional uint32 missed_entries = 6; - - repeated DisplayProto displays = 7; - - optional int64 vsync_id = 8; -} diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto deleted file mode 100644 index d03afa05ab..0000000000 --- a/services/surfaceflinger/layerproto/transactions.proto +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; -option optimize_for = LITE_RUNTIME; - -import "frameworks/native/services/surfaceflinger/layerproto/common.proto"; - -package android.surfaceflinger.proto; - -/* Represents a file full of surface flinger transactions. - Encoded, it should start with 0x54 0x4E 0x58 0x54 0x52 0x41 0x43 0x45 (.TNXTRACE), such - that they can be easily identified. */ -message TransactionTraceFile { - /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L - (this is needed because enums have to be 32 bits and there's no nice way to put 64bit - constants into .proto files. */ - enum MagicNumber { - INVALID = 0; - MAGIC_NUMBER_L = 0x54584E54; /* TNXT (little-endian ASCII) */ - MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */ - } - - fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */ - repeated TransactionTraceEntry entry = 2; - - /* offset between real-time clock and elapsed time clock in nanoseconds. - Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */ - fixed64 real_to_elapsed_time_offset_nanos = 3; - uint32 version = 4; -} - -message TransactionTraceEntry { - int64 elapsed_realtime_nanos = 1; - int64 vsync_id = 2; - repeated TransactionState transactions = 3; - repeated LayerCreationArgs added_layers = 4; - repeated uint32 destroyed_layers = 5; - repeated DisplayState added_displays = 6; - repeated int32 removed_displays = 7; - repeated uint32 destroyed_layer_handles = 8; - bool displays_changed = 9; - repeated DisplayInfo displays = 10; -} - -message DisplayInfo { - uint32 layer_stack = 1; - int32 display_id = 2; - int32 logical_width = 3; - int32 logical_height = 4; - Transform transform_inverse = 5; - Transform transform = 6; - bool receives_input = 7; - bool is_secure = 8; - bool is_primary = 9; - bool is_virtual = 10; - int32 rotation_flags = 11; - int32 transform_hint = 12; - -} - -message LayerCreationArgs { - uint32 layer_id = 1; - string name = 2; - uint32 flags = 3; - uint32 parent_id = 4; - uint32 mirror_from_id = 5; - bool add_to_root = 6; - uint32 layer_stack_to_mirror = 7; -} - -message Transform { - float dsdx = 1; - float dtdx = 2; - float dtdy = 3; - float dsdy = 4; - float tx = 5; - float ty = 6; -} - -message TransactionState { - int32 pid = 1; - int32 uid = 2; - int64 vsync_id = 3; - int32 input_event_id = 4; - int64 post_time = 5; - uint64 transaction_id = 6; - repeated LayerState layer_changes = 7; - repeated DisplayState display_changes = 8; - repeated uint64 merged_transaction_ids = 9; -} - -// Keep insync with layer_state_t -message LayerState { - uint32 layer_id = 1; - // Changes are split into ChangesLsb and ChangesMsb. First 32 bits are in ChangesLsb - // and the next 32 bits are in ChangesMsb. This is needed because enums have to be - // 32 bits and there's no nice way to put 64bit constants into .proto files. - enum ChangesLsb { - eChangesLsbNone = 0; - ePositionChanged = 0x00000001; - eLayerChanged = 0x00000002; - // unused = 0x00000004; - eAlphaChanged = 0x00000008; - - eMatrixChanged = 0x00000010; - eTransparentRegionChanged = 0x00000020; - eFlagsChanged = 0x00000040; - eLayerStackChanged = 0x00000080; - - eReleaseBufferListenerChanged = 0x00000400; - eShadowRadiusChanged = 0x00000800; - - eBufferCropChanged = 0x00002000; - eRelativeLayerChanged = 0x00004000; - eReparent = 0x00008000; - - eColorChanged = 0x00010000; - eBufferTransformChanged = 0x00040000; - eTransformToDisplayInverseChanged = 0x00080000; - - eCropChanged = 0x00100000; - eBufferChanged = 0x00200000; - eAcquireFenceChanged = 0x00400000; - eDataspaceChanged = 0x00800000; - - eHdrMetadataChanged = 0x01000000; - eSurfaceDamageRegionChanged = 0x02000000; - eApiChanged = 0x04000000; - eSidebandStreamChanged = 0x08000000; - - eColorTransformChanged = 0x10000000; - eHasListenerCallbacksChanged = 0x20000000; - eInputInfoChanged = 0x40000000; - eCornerRadiusChanged = -2147483648; // 0x80000000; (proto stores enums as signed int) - }; - enum ChangesMsb { - eChangesMsbNone = 0; - eDestinationFrameChanged = 0x1; - eCachedBufferChanged = 0x2; - eBackgroundColorChanged = 0x4; - eMetadataChanged = 0x8; - eColorSpaceAgnosticChanged = 0x10; - eFrameRateSelectionPriority = 0x20; - eFrameRateChanged = 0x40; - eBackgroundBlurRadiusChanged = 0x80; - eProducerDisconnect = 0x100; - eFixedTransformHintChanged = 0x200; - eFrameNumberChanged = 0x400; - eBlurRegionsChanged = 0x800; - eAutoRefreshChanged = 0x1000; - eStretchChanged = 0x2000; - eTrustedOverlayChanged = 0x4000; - eDropInputModeChanged = 0x8000; - }; - uint64 what = 2; - float x = 3; - float y = 4; - int32 z = 5; - uint32 w = 6; - uint32 h = 7; - uint32 layer_stack = 8; - - enum Flags { - eFlagsNone = 0; - eLayerHidden = 0x01; - eLayerOpaque = 0x02; - eLayerSkipScreenshot = 0x40; - eLayerSecure = 0x80; - eEnableBackpressure = 0x100; - eLayerIsDisplayDecoration = 0x200; - }; - uint32 flags = 9; - uint32 mask = 10; - - message Matrix22 { - float dsdx = 1; - float dtdx = 2; - float dtdy = 3; - float dsdy = 4; - }; - Matrix22 matrix = 11; - float corner_radius = 12; - uint32 background_blur_radius = 13; - uint32 parent_id = 14; - uint32 relative_parent_id = 15; - - float alpha = 16; - message Color3 { - float r = 1; - float g = 2; - float b = 3; - } - Color3 color = 17; - RegionProto transparent_region = 18; - uint32 transform = 19; - bool transform_to_display_inverse = 20; - RectProto crop = 21; - - message BufferData { - uint64 buffer_id = 1; - uint32 width = 2; - uint32 height = 3; - uint64 frame_number = 4; - - enum BufferDataChange { - BufferDataChangeNone = 0; - fenceChanged = 0x01; - frameNumberChanged = 0x02; - cachedBufferChanged = 0x04; - } - uint32 flags = 5; - uint64 cached_buffer_id = 6; - - enum PixelFormat { - PIXEL_FORMAT_UNKNOWN = 0; - PIXEL_FORMAT_CUSTOM = -4; - PIXEL_FORMAT_TRANSLUCENT = -3; - PIXEL_FORMAT_TRANSPARENT = -2; - PIXEL_FORMAT_OPAQUE = -1; - PIXEL_FORMAT_RGBA_8888 = 1; - PIXEL_FORMAT_RGBX_8888 = 2; - PIXEL_FORMAT_RGB_888 = 3; - PIXEL_FORMAT_RGB_565 = 4; - PIXEL_FORMAT_BGRA_8888 = 5; - PIXEL_FORMAT_RGBA_5551 = 6; - PIXEL_FORMAT_RGBA_4444 = 7; - PIXEL_FORMAT_RGBA_FP16 = 22; - PIXEL_FORMAT_RGBA_1010102 = 43; - PIXEL_FORMAT_R_8 = 0x38; - } - PixelFormat pixel_format = 7; - uint64 usage = 8; - } - BufferData buffer_data = 22; - int32 api = 23; - bool has_sideband_stream = 24; - ColorTransformProto color_transform = 25; - repeated BlurRegion blur_regions = 26; - - message WindowInfo { - uint32 layout_params_flags = 1; - int32 layout_params_type = 2; - RegionProto touchable_region = 3; - int32 surface_inset = 4; - bool focusable = 5; // unused - bool has_wallpaper = 6; // unused - float global_scale_factor = 7; - uint32 crop_layer_id = 8; - bool replace_touchable_region_with_crop = 9; - RectProto touchable_region_crop = 10; - Transform transform = 11; - uint32 input_config = 12; - } - WindowInfo window_info_handle = 27; - float bg_color_alpha = 28; - int32 bg_color_dataspace = 29; - bool color_space_agnostic = 30; - float shadow_radius = 31; - int32 frame_rate_selection_priority = 32; - float frame_rate = 33; - int32 frame_rate_compatibility = 34; - int32 change_frame_rate_strategy = 35; - uint32 fixed_transform_hint = 36; - uint64 frame_number = 37; - bool auto_refresh = 38; - bool is_trusted_overlay = 39; - RectProto buffer_crop = 40; - RectProto destination_frame = 41; - - enum DropInputMode { - NONE = 0; - ALL = 1; - OBSCURED = 2; - }; - DropInputMode drop_input_mode = 42; -} - -message DisplayState { - enum Changes { - eChangesNone = 0; - eSurfaceChanged = 0x01; - eLayerStackChanged = 0x02; - eDisplayProjectionChanged = 0x04; - eDisplaySizeChanged = 0x08; - eFlagsChanged = 0x10; - }; - int32 id = 1; - uint32 what = 2; - uint32 flags = 3; - uint32 layer_stack = 4; - uint32 orientation = 5; - RectProto layer_stack_space_rect = 6; - RectProto oriented_display_space_rect = 7; - uint32 width = 8; - uint32 height = 9; -} diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index 03201f7937..b30df5ef15 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -51,9 +51,9 @@ TEST(SurfaceFlingerStress, create_and_destroy) { } } -surfaceflinger::LayersProto generateLayerProto() { - surfaceflinger::LayersProto layersProto; - std::array layers = {}; +perfetto::protos::LayersProto generateLayerProto() { + perfetto::protos::LayersProto layersProto; + std::array layers = {}; for (size_t i = 0; i < layers.size(); ++i) { layers[i] = layersProto.add_layers(); layers[i]->set_id(i); @@ -103,7 +103,7 @@ TEST(LayerProtoStress, mem_info) { cmd += std::to_string(getpid()); system(cmd.c_str()); for (int i = 0; i < 100000; i++) { - surfaceflinger::LayersProto layersProto = generateLayerProto(); + perfetto::protos::LayersProto layersProto = generateLayerProto(); auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto); surfaceflinger::LayerProtoParser::layerTreeToString(layerTree); } diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp index b8a5e79a38..333768a92a 100644 --- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp +++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp @@ -149,7 +149,7 @@ static LayerInfo getLayerInfoFromProto(::android::surfaceflinger::LayerProto& pr } static std::vector getLayerInfosFromProto( - android::surfaceflinger::LayersTraceProto& entry) { + perfetto::protos::pbzero::LayersSnapshotProto& entry) { std::unordered_map snapshotIdToLayerId; std::vector layers; layers.reserve(static_cast(entry.layers().layers_size())); @@ -267,4 +267,4 @@ int main(int argc, char** argv) { } ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +} diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp index a95a6453d5..cbb597af69 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -85,7 +85,7 @@ TEST(TransactionProtoParserTest, parse) { TransactionProtoParser parser(std::make_unique(displayHandle)); - proto::TransactionState proto = parser.toProto(t1); + perfetto::protos::TransactionState proto = parser.toProto(t1); TransactionState t2 = parser.fromProto(proto); ASSERT_EQ(t1.originPid, t2.originPid); @@ -119,7 +119,7 @@ TEST(TransactionProtoParserTest, parseDisplayInfo) { d1.transformHint = ui::Transform::ROT_90; const uint32_t layerStack = 2; - google::protobuf::RepeatedPtrField displayProtos; + google::protobuf::RepeatedPtrField displayProtos; auto displayInfoProto = displayProtos.Add(); *displayInfoProto = TransactionProtoParser::toProto(d1, layerStack); frontend::DisplayInfos displayInfos; diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp index 71a2d2b9a6..7981224b5c 100644 --- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp @@ -37,11 +37,11 @@ protected: TransactionTracing mTracing; void flush() { mTracing.flush(); } - proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } + perfetto::protos::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } - proto::TransactionTraceEntry bufferFront() { + perfetto::protos::TransactionTraceEntry bufferFront() { std::scoped_lock lock(mTracing.mTraceLock); - proto::TransactionTraceEntry entry; + perfetto::protos::TransactionTraceEntry entry; entry.ParseFromString(mTracing.mBuffer.front()); return entry; } @@ -59,7 +59,7 @@ protected: flush(); } - void verifyEntry(const proto::TransactionTraceEntry& actualProto, + void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto, const std::vector& expectedTransactions, int64_t expectedVsyncId) { EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId); @@ -117,7 +117,7 @@ TEST_F(TransactionTracingTest, addTransactions) { mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false); flush(); - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); ASSERT_EQ(proto.entry().size(), 2); verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId); verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId); @@ -203,7 +203,7 @@ TEST_F(TransactionTracingLayerHandlingTest, addStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify we can still retrieve the layer change from the first entry containing starting // states. EXPECT_GT(proto.entry().size(), 0); @@ -221,7 +221,7 @@ TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify starting states are updated correctly EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41); } @@ -231,7 +231,7 @@ TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) { while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify the child layer has been removed from the trace EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1); EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId); @@ -242,7 +242,7 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) { while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) { queueAndCommitTransaction(++mVsyncId); } - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // verify we have two starting states EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2); @@ -302,7 +302,7 @@ protected: }; TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { - proto::TransactionTraceFile proto = writeToProto(); + perfetto::protos::TransactionTraceFile proto = writeToProto(); // We don't have any starting states since no layer was removed from. EXPECT_EQ(proto.entry().size(), 1); @@ -317,18 +317,18 @@ TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { // Verify we can write the layers traces by entry to reduce mem pressure // on the system when generating large traces. TEST(LayerTraceTest, canStreamLayersTrace) { - LayersTraceFileProto inProto = LayerTracing::createTraceFileProto(); + perfetto::protos::LayersTraceFileProto inProto = LayerTracing::createTraceFileProto(); inProto.add_entry(); inProto.add_entry(); std::string output; inProto.SerializeToString(&output); - LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto(); + perfetto::protos::LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto(); inProto2.add_entry(); std::string output2; inProto2.SerializeToString(&output2); - LayersTraceFileProto outProto; + perfetto::protos::LayersTraceFileProto outProto; outProto.ParseFromString(output + output2); // magic? EXPECT_EQ(outProto.entry().size(), 3); -- cgit v1.2.3-59-g8ed1b From 7941ecfe603da0955783c5368ae1959aaaaf89c0 Mon Sep 17 00:00:00 2001 From: Kean Mariotti Date: Thu, 27 Apr 2023 16:42:13 +0000 Subject: Revert^2 Revert layer proto format back to proto2 Perfetto doesn't support proto3, hence reverted to proto2. This reverts commit dcc0bab76dbf3156f18e4dd2697aa7220ad7a8e0 Bug: b/284424784 Test: atest libsurfaceflinger_unittest && atest transactiontrace_testsuite Change-Id: I107a56f57f547056c44877e776d169dd21db618a --- services/surfaceflinger/Layer.cpp | 4 ---- services/surfaceflinger/layerproto/LayerProtoParser.cpp | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d4babdbd79..9a5173ba9b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2325,15 +2325,11 @@ void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote(); if (parent != nullptr) { layerInfo->set_parent(parent->sequence); - } else { - layerInfo->set_parent(-1); } auto zOrderRelativeOf = state.zOrderRelativeOf.promote(); if (zOrderRelativeOf != nullptr) { layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence); - } else { - layerInfo->set_z_order_relative_of(-1); } layerInfo->set_is_relative_of(state.isRelativeOf); diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index 8d48070e13..c3d0a40261 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -193,13 +193,13 @@ void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerPr } } - if (layerProto.parent() != -1) { + if (layerProto.has_parent()) { if (layerMap.count(layerProto.parent()) > 0) { currLayer->parent = layerMap[layerProto.parent()]; } } - if (layerProto.z_order_relative_of() != -1) { + if (layerProto.has_z_order_relative_of()) { if (layerMap.count(layerProto.z_order_relative_of()) > 0) { currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()]; } -- cgit v1.2.3-59-g8ed1b From e5374e50fe60e410ff94f20cb64dadcdf18c8ee5 Mon Sep 17 00:00:00 2001 From: Dorin Drimus Date: Wed, 2 Aug 2023 17:52:43 +0000 Subject: Clear unexpected buffer handle of sideband layer If the buffer handle is not cleared after MediaCodec disconnected and the surface is re-used for another sideband stream. SurfaceFlinger would trigger incorrect composition type change from sideband to device when SurfaceView layout changed. Clear the buffer if the layer was about to set a new sideband handle. Bug: 291202822 Test: Adjust the screen layout after played 2 different sideband stream. No composition type change. Change-Id: I0b42d68ea03fb09db9aefc257d6071e559a3d8d2 --- services/surfaceflinger/Layer.cpp | 65 ++++++++++++++-------- services/surfaceflinger/Layer.h | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 6 +- .../fuzzer/surfaceflinger_layer_fuzzer.cpp | 3 +- .../unittests/TunnelModeEnabledReporterTest.cpp | 4 +- 5 files changed, 52 insertions(+), 30 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9a5173ba9b..047d376ee4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3092,6 +3092,32 @@ bool Layer::setPosition(float x, float y) { return true; } +void Layer::releasePreviousBuffer() { + mReleasePreviousBuffer = true; + if (!mBufferInfo.mBuffer || + (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) || + mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) { + // If mDrawingState has a buffer, and we are about to update again + // before swapping to drawing state, then the first buffer will be + // dropped and we should decrement the pending buffer count and + // call any release buffer callbacks if set. + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber, + mDrawingState.acquireFence); + decrementPendingBufferCount(); + if (mDrawingState.bufferSurfaceFrameTX != nullptr && + mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) { + addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime()); + mDrawingState.bufferSurfaceFrameTX.reset(); + } + } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) { + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber, + mLastClientCompositionFence); + mLastClientCompositionFence = nullptr; + } +} + void Layer::resetDrawingStateBufferInfo() { mDrawingState.producerId = 0; mDrawingState.frameNumber = 0; @@ -3116,29 +3142,7 @@ bool Layer::setBuffer(std::shared_ptr& buffer, ATRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber); if (mDrawingState.buffer) { - mReleasePreviousBuffer = true; - if (!mBufferInfo.mBuffer || - (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) || - mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) { - // If mDrawingState has a buffer, and we are about to update again - // before swapping to drawing state, then the first buffer will be - // dropped and we should decrement the pending buffer count and - // call any release buffer callbacks if set. - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber, - mDrawingState.acquireFence); - decrementPendingBufferCount(); - if (mDrawingState.bufferSurfaceFrameTX != nullptr && - mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) { - addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime()); - mDrawingState.bufferSurfaceFrameTX.reset(); - } - } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) { - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber, - mLastClientCompositionFence); - mLastClientCompositionFence = nullptr; - } + releasePreviousBuffer(); } else if (buffer) { // if we are latching a buffer for the first time then clear the mLastLatchTime since // we don't want to incorrectly classify a frame if we miss the desired present time. @@ -3156,6 +3160,12 @@ bool Layer::setBuffer(std::shared_ptr& buffer, mDrawingState.bufferSurfaceFrameTX = nullptr; setFrameTimelineVsyncForBufferlessTransaction(info, postTime); return true; + } else { + // release sideband stream if it exists and a non null buffer is being set + if (mDrawingState.sidebandStream != nullptr) { + mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount(); + mDrawingState.sidebandStream = nullptr; + } } if ((mDrawingState.producerId > bufferData.producerId) || @@ -3344,7 +3354,8 @@ bool Layer::setApi(int32_t api) { return true; } -bool Layer::setSidebandStream(const sp& sidebandStream) { +bool Layer::setSidebandStream(const sp& sidebandStream, const FrameTimelineInfo& info, + nsecs_t postTime) { if (mDrawingState.sidebandStream == sidebandStream) return false; if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) { @@ -3355,6 +3366,12 @@ bool Layer::setSidebandStream(const sp& sidebandStream) { mDrawingState.sidebandStream = sidebandStream; mDrawingState.modified = true; + if (sidebandStream != nullptr && mDrawingState.buffer != nullptr) { + releasePreviousBuffer(); + resetDrawingStateBufferInfo(); + mDrawingState.bufferSurfaceFrameTX = nullptr; + setFrameTimelineVsyncForBufferlessTransaction(info, postTime); + } setTransactionFlags(eTransactionNeeded); if (!mSidebandStreamChanged.exchange(true)) { // mSidebandStreamChanged was false diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index dc4ceb0bfa..0b0cef54bf 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -317,7 +317,8 @@ public: bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/); bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/); bool setApi(int32_t /*api*/); - bool setSidebandStream(const sp& /*sidebandStream*/); + bool setSidebandStream(const sp& /*sidebandStream*/, + const FrameTimelineInfo& /* info*/, nsecs_t /* postTime */); bool setTransactionCompletedListeners(const std::vector>& /*handles*/, bool willPresent); virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) @@ -1204,6 +1205,7 @@ private: half4 mBorderColor; void setTransformHintLegacy(ui::Transform::RotationFlags); + void releasePreviousBuffer(); void resetDrawingStateBufferInfo(); // Transform hint provided to the producer. This must be accessed holding diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 517dc96195..4adcd55f4c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5139,7 +5139,8 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime if (layer->setApi(s.api)) flags |= eTraversalNeeded; } if (what & layer_state_t::eSidebandStreamChanged) { - if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; + if (layer->setSidebandStream(s.sidebandStream, frameTimelineInfo, postTime)) + flags |= eTraversalNeeded; } if (what & layer_state_t::eInputInfoChanged) { layer->setInputInfo(*s.windowInfoHandle->getInfo()); @@ -5383,7 +5384,8 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } if (what & layer_state_t::eSidebandStreamChanged) { - if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded; + if (layer->setSidebandStream(s.sidebandStream, frameTimelineInfo, postTime)) + flags |= eTraversalNeeded; } if (what & layer_state_t::eDataspaceChanged) { if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp index 9f0bddea1e..39a7ee5c12 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp @@ -153,7 +153,8 @@ void LayerFuzzer::invokeBufferStateLayer() { native_handle_t* testHandle = native_handle_create(0, 1); const bool ownsHandle = mFdp.ConsumeBool(); sp nativeHandle = sp::make(testHandle, ownsHandle); - layer->setSidebandStream(nativeHandle); + layer->setSidebandStream(nativeHandle, getFuzzedFrameTimelineInfo(), + mFdp.ConsumeIntegral() /* postTime */); layer->computeSourceBounds(getFuzzedFloatRect(&mFdp)); layer->fenceHasSignaled(); diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp index 108151ec65..1cf14ae519 100644 --- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp +++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp @@ -127,7 +127,7 @@ TEST_F(TunnelModeEnabledReporterTest, callsNewListenerWithFreshInformation) { sp stream = NativeHandle::create(reinterpret_cast(DEFAULT_SIDEBAND_STREAM), false); - layer->setSidebandStream(stream); + layer->setSidebandStream(stream, FrameTimelineInfo{}, 20); mFlinger.mutableCurrentState().layersSortedByZ.add(layer); mTunnelModeEnabledReporter->updateTunnelModeStatus(); mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener); @@ -151,7 +151,7 @@ TEST_F(TunnelModeEnabledReporterTest, layerWithSidebandStreamTriggersUpdate) { sp stream = NativeHandle::create(reinterpret_cast(DEFAULT_SIDEBAND_STREAM), false); - layerWithSidebandStream->setSidebandStream(stream); + layerWithSidebandStream->setSidebandStream(stream, FrameTimelineInfo{}, 20); mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer); mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream); -- cgit v1.2.3-59-g8ed1b From 6f87831da64222a3341498de174ee7ce2c8a905b Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 8 Sep 2023 11:05:01 -0700 Subject: [sf-newfe] Fix snapshot paths for recursive mirror paths If we are mirroring a hierarchy that already contains a mirror then we need to track all the mirror roots inorder to have a unique path. Test: presubmit Test: can screenrecord magnifier Test: dumpsys SurfaceFlinger --frontend Bug: 238781169 Change-Id: Id2272981f6f6244f41328428b73184bccf5d1888 --- .../surfaceflinger/FrontEnd/LayerHierarchy.cpp | 30 +++++++++---------- services/surfaceflinger/FrontEnd/LayerHierarchy.h | 35 +++++++++++++--------- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 7 +++-- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 33 ++++++++++++++++++++ services/surfaceflinger/SurfaceFlinger.h | 1 + .../tests/unittests/LayerHierarchyTest.cpp | 18 +++++++++++ .../tests/unittests/LayerSnapshotTest.cpp | 21 +++++++++++-- 8 files changed, 112 insertions(+), 35 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 962dc09680..1e5a6fbd1e 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -145,7 +145,8 @@ std::string LayerHierarchy::getDebugStringShort() const { } void LayerHierarchy::dump(std::ostream& out, const std::string& prefix, - LayerHierarchy::Variant variant, bool isLastChild) const { + LayerHierarchy::Variant variant, bool isLastChild, + bool includeMirroredHierarchy) const { if (!mLayer) { out << " ROOT"; } else { @@ -153,8 +154,11 @@ void LayerHierarchy::dump(std::ostream& out, const std::string& prefix, if (variant == LayerHierarchy::Variant::Relative) { out << "(Relative) "; } else if (variant == LayerHierarchy::Variant::Mirror) { - out << "(Mirroring) " << *mLayer << "\n" + prefix + " └─ ..."; - return; + if (!includeMirroredHierarchy) { + out << "(Mirroring) " << *mLayer << "\n" + prefix + " └─ ..."; + return; + } + out << "(Mirroring) "; } out << *mLayer; } @@ -168,7 +172,7 @@ void LayerHierarchy::dump(std::ostream& out, const std::string& prefix, childPrefix += (isLastChild ? " " : "│ "); } out << "\n"; - child->dump(out, childPrefix, childVariant, lastChild); + child->dump(out, childPrefix, childVariant, lastChild, includeMirroredHierarchy); } return; } @@ -435,8 +439,11 @@ std::string LayerHierarchy::TraversalPath::toString() const { std::stringstream ss; ss << "TraversalPath{.id = " << id; - if (mirrorRootId != UNASSIGNED_LAYER_ID) { - ss << ", .mirrorRootId=" << mirrorRootId; + if (!mirrorRootIds.empty()) { + ss << ", .mirrorRootIds="; + for (auto rootId : mirrorRootIds) { + ss << rootId << ","; + } } if (!relativeRootIds.empty()) { @@ -453,13 +460,6 @@ std::string LayerHierarchy::TraversalPath::toString() const { return ss.str(); } -LayerHierarchy::TraversalPath LayerHierarchy::TraversalPath::getMirrorRoot() const { - LLOG_ALWAYS_FATAL_WITH_TRACE_IF(!isClone(), "Cannot get mirror root of a non cloned node"); - TraversalPath mirrorRootPath = *this; - mirrorRootPath.id = mirrorRootId; - return mirrorRootPath; -} - // Helper class to update a passed in TraversalPath when visiting a child. When the object goes out // of scope the TraversalPath is reset to its original state. LayerHierarchy::ScopedAddToTraversalPath::ScopedAddToTraversalPath(TraversalPath& traversalPath, @@ -471,7 +471,7 @@ LayerHierarchy::ScopedAddToTraversalPath::ScopedAddToTraversalPath(TraversalPath traversalPath.id = layerId; traversalPath.variant = variant; if (variant == LayerHierarchy::Variant::Mirror) { - traversalPath.mirrorRootId = mParentPath.id; + traversalPath.mirrorRootIds.emplace_back(mParentPath.id); } else if (variant == LayerHierarchy::Variant::Relative) { if (std::find(traversalPath.relativeRootIds.begin(), traversalPath.relativeRootIds.end(), layerId) != traversalPath.relativeRootIds.end()) { @@ -486,7 +486,7 @@ LayerHierarchy::ScopedAddToTraversalPath::~ScopedAddToTraversalPath() { // Reset the traversal id to its original parent state using the state that was saved in // the constructor. if (mTraversalPath.variant == LayerHierarchy::Variant::Mirror) { - mTraversalPath.mirrorRootId = mParentPath.mirrorRootId; + mTraversalPath.mirrorRootIds.pop_back(); } else if (mTraversalPath.variant == LayerHierarchy::Variant::Relative) { mTraversalPath.relativeRootIds.pop_back(); } diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index 1e4838727b..ba2e262baf 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -57,25 +57,25 @@ public: // ├─ B {Traversal path id = 2} // │ ├─ C {Traversal path id = 3} // │ ├─ D {Traversal path id = 4} - // │ └─ E {Traversal path id = 5} - // ├─ F (Mirrors B) {Traversal path id = 6} - // └─ G (Mirrors F) {Traversal path id = 7} + // │ └─ E (Mirrors C) {Traversal path id = 5} + // └─ F (Mirrors B) {Traversal path id = 6} // - // C, D and E can be traversed via B or via F then B or via G then F then B. + // C can be traversed via B or E or F and or via F then E. // Depending on how the node is reached, its properties such as geometry or visibility might be // different. And we can uniquely identify the node by keeping track of the nodes leading up to // it. But to be more efficient we only need to track the nodes id and the top mirror root path. // So C for example, would have the following unique traversal paths: // - {Traversal path id = 3} - // - {Traversal path id = 3, mirrorRootId = 6} - // - {Traversal path id = 3, mirrorRootId = 7} + // - {Traversal path id = 3, mirrorRootIds = 5} + // - {Traversal path id = 3, mirrorRootIds = 6} + // - {Traversal path id = 3, mirrorRootIds = 6, 5} struct TraversalPath { uint32_t id; LayerHierarchy::Variant variant; // Mirrored layers can have a different geometry than their parents so we need to track // the mirror roots in the traversal. - uint32_t mirrorRootId = UNASSIGNED_LAYER_ID; + ftl::SmallVector mirrorRootIds; // Relative layers can be visited twice, once by their parent and then once again by // their relative parent. We keep track of the roots here to detect any loops in the // hierarchy. If a relative root already exists in the list while building the @@ -93,11 +93,10 @@ public: // Returns true if the node or its parents are not Detached. bool isAttached() const { return !detached; } // Returns true if the node is a clone. - bool isClone() const { return mirrorRootId != UNASSIGNED_LAYER_ID; } - TraversalPath getMirrorRoot() const; + bool isClone() const { return !mirrorRootIds.empty(); } bool operator==(const TraversalPath& other) const { - return id == other.id && mirrorRootId == other.mirrorRootId; + return id == other.id && mirrorRootIds == other.mirrorRootIds; } std::string toString() const; @@ -107,8 +106,8 @@ public: struct TraversalPathHash { std::size_t operator()(const LayerHierarchy::TraversalPath& key) const { uint32_t hashCode = key.id * 31; - if (key.mirrorRootId != UNASSIGNED_LAYER_ID) { - hashCode += key.mirrorRootId * 31; + for (uint32_t mirrorRootId : key.mirrorRootIds) { + hashCode += mirrorRootId * 31; } return std::hash{}(hashCode); } @@ -158,9 +157,17 @@ public: const LayerHierarchy* getParent() const; friend std::ostream& operator<<(std::ostream& os, const LayerHierarchy& obj) { std::string prefix = " "; - obj.dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false); + obj.dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false, + /*includeMirroredHierarchy*/ false); return os; } + std::string dump() const { + std::string prefix = " "; + std::ostringstream os; + dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false, + /*includeMirroredHierarchy*/ true); + return os.str(); + } std::string getDebugStringShort() const; // Traverse the hierarchy and return true if loops are found. The outInvalidRelativeRoot @@ -178,7 +185,7 @@ private: void traverseInZOrder(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const; void traverse(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const; void dump(std::ostream& out, const std::string& prefix, LayerHierarchy::Variant variant, - bool isLastChild) const; + bool isLastChild, bool includeMirroredHierarchy) const; const RequestedLayerState* mLayer; LayerHierarchy* mParent = nullptr; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 80bedf4a39..899d2dedaf 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -294,8 +294,11 @@ std::string LayerSnapshot::getDebugString() const { std::ostream& operator<<(std::ostream& out, const LayerSnapshot& obj) { out << "Layer [" << obj.path.id; - if (obj.path.mirrorRootId != UNASSIGNED_LAYER_ID) { - out << " mirrored from " << obj.path.mirrorRootId; + if (!obj.path.mirrorRootIds.empty()) { + out << " mirrored from "; + for (auto rootId : obj.path.mirrorRootIds) { + out << rootId << ","; + } } out << "] " << obj.name << "\n " << (obj.isVisible ? "visible" : "invisible") << " reason=" << obj.getIsVisibleReason(); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9a5173ba9b..2bbfa42358 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2648,7 +2648,7 @@ Region Layer::getVisibleRegion(const DisplayDevice* display) const { void Layer::setInitialValuesForClone(const sp& clonedFrom, uint32_t mirrorRootId) { mSnapshot->path.id = clonedFrom->getSequence(); - mSnapshot->path.mirrorRootId = mirrorRootId; + mSnapshot->path.mirrorRootIds.emplace_back(mirrorRootId); cloneDrawingState(clonedFrom.get()); mClonedFrom = clonedFrom; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 517dc96195..92e4881941 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5823,6 +5823,7 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)}, {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)}, {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)}, + {"--frontend"s, dumper(&SurfaceFlinger::dumpFrontEnd)}, }; const auto flag = args.empty() ? ""s : std::string(String8(args[0])); @@ -6132,6 +6133,38 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } +void SurfaceFlinger::dumpFrontEnd(std::string& result) { + mScheduler + ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { + std::ostringstream out; + out << "\nComposition list\n"; + ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; + for (const auto& snapshot : mLayerSnapshotBuilder.getSnapshots()) { + if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) { + lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack; + out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; + } + out << " " << *snapshot << "\n"; + } + + out << "\nInput list\n"; + lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK; + mLayerSnapshotBuilder.forEachInputSnapshot( + [&](const frontend::LayerSnapshot& snapshot) { + if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) { + lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack; + out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n"; + } + out << " " << snapshot << "\n"; + }); + + out << "\nLayer Hierarchy\n" + << mLayerHierarchyBuilder.getHierarchy().dump() << "\n\n"; + result.append(out.str()); + }) + .get(); +} + perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { std::unordered_set stackIdsToSkip; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 59b1172edc..8fa5de7f30 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1090,6 +1090,7 @@ private: void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock); + void dumpFrontEnd(std::string& result); perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const; void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto, diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp index e4f49e863b..95f19406b4 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp @@ -736,4 +736,22 @@ TEST_F(LayerHierarchyTest, removedRootLayerIsNoLongerMirrored) { EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expected); } +TEST_F(LayerHierarchyTest, canMirrorDisplayWithMirrors) { + LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers()); + reparentLayer(12, UNASSIGNED_LAYER_ID); + mirrorLayer(/*layer*/ 14, /*parent*/ 1, /*layerToMirror*/ 11); + UPDATE_AND_VERIFY(hierarchyBuilder); + + createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0)); + setLayerStack(3, 1); + UPDATE_AND_VERIFY(hierarchyBuilder); + + std::vector expected = {1, 11, 111, 13, 14, 11, 111, 2, 3, + 1, 11, 111, 13, 14, 11, 111, 2}; + EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expected); + EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expected); + expected = {12, 121, 122, 1221}; + EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expected); +} + } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 23534802cc..1227b994dd 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -410,8 +410,8 @@ TEST_F(LayerSnapshotTest, mirrorLayerGetsCorrectLayerStack) { std::vector expected = {1, 11, 111, 13, 2, 3, 1, 11, 111, 13, 2, 4, 1, 11, 111, 13, 2}; UPDATE_AND_VERIFY(mSnapshotBuilder, expected); - EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 3})->outputFilter.layerStack.id, 3u); - EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 4})->outputFilter.layerStack.id, 4u); + EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootIds = 3u})->outputFilter.layerStack.id, 3u); + EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootIds = 4u})->outputFilter.layerStack.id, 4u); } // ROOT (DISPLAY 0) @@ -435,7 +435,7 @@ TEST_F(LayerSnapshotTest, mirrorLayerTouchIsCroppedByMirrorRoot) { UPDATE_AND_VERIFY(mSnapshotBuilder, expected); EXPECT_TRUE(getSnapshot({.id = 111})->inputInfo.touchableRegion.hasSameRects(touch)); Region touchCroppedByMirrorRoot{Rect{0, 0, 50, 50}}; - EXPECT_TRUE(getSnapshot({.id = 111, .mirrorRootId = 3}) + EXPECT_TRUE(getSnapshot({.id = 111, .mirrorRootIds = 3u}) ->inputInfo.touchableRegion.hasSameRects(touchCroppedByMirrorRoot)); } @@ -462,6 +462,21 @@ TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterMirroring) { EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size()); } +TEST_F(LayerSnapshotTest, canMirrorDisplayWithMirrors) { + reparentLayer(12, UNASSIGNED_LAYER_ID); + mirrorLayer(/*layer*/ 14, /*parent*/ 1, /*layerToMirror*/ 11); + std::vector expected = {1, 11, 111, 13, 14, 11, 111, 2}; + UPDATE_AND_VERIFY(mSnapshotBuilder, expected); + + createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0)); + setLayerStack(3, 3); + expected = {1, 11, 111, 13, 14, 11, 111, 2, 3, 1, 11, 111, 13, 14, 11, 111, 2}; + UPDATE_AND_VERIFY(mSnapshotBuilder, expected); + EXPECT_EQ(getSnapshot({.id = 11, .mirrorRootIds = 14u})->outputFilter.layerStack.id, 0u); + EXPECT_EQ(getSnapshot({.id = 11, .mirrorRootIds = 3u})->outputFilter.layerStack.id, 3u); + EXPECT_EQ(getSnapshot({.id = 11, .mirrorRootIds = 3u, 14u})->outputFilter.layerStack.id, 3u); +} + // Rel z doesn't create duplicate snapshots but this is for completeness TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterRelZ) { size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size(); -- cgit v1.2.3-59-g8ed1b From 58cc90d352b71bd1be16d4a89053350bbeada0af Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Tue, 5 Sep 2023 18:50:20 -0700 Subject: Plumb new frameRateSelectionStrategy value This new value will allow a parent layer to override the frame rate specifications of all its descendants. This CL only plumbs the value from Transaction to Layer. Bug: 297418260 Test: atest CtsSurfaceControlTestsStaging Test: atest libsurfaceflinger_unittest Change-Id: Ibbda6ff6c143e931240178d89306822b4cce9669 --- libs/gui/LayerState.cpp | 8 ++++ libs/gui/SurfaceComposerClient.cpp | 13 +++++++ libs/gui/include/gui/LayerState.h | 6 ++- libs/gui/include/gui/SurfaceComposerClient.h | 2 + libs/nativewindow/include/system/window.h | 20 ++++++++++ services/surfaceflinger/FrontEnd/LayerSnapshot.h | 1 + .../FrontEnd/LayerSnapshotBuilder.cpp | 16 +++++++- .../FrontEnd/RequestedLayerState.cpp | 2 + services/surfaceflinger/Layer.cpp | 10 +++++ services/surfaceflinger/Layer.h | 5 +++ services/surfaceflinger/Scheduler/LayerInfo.cpp | 13 +++++++ services/surfaceflinger/Scheduler/LayerInfo.h | 15 +++++++- services/surfaceflinger/SurfaceFlinger.cpp | 8 ++++ .../tests/unittests/LayerHierarchyTest.h | 12 ++++++ .../tests/unittests/LayerSnapshotTest.cpp | 44 ++++++++++++++++++++++ 15 files changed, 170 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e1afb524e7..27b1d8b09b 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -84,6 +84,7 @@ layer_state_t::layer_state_t() changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS), defaultFrameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), frameRateCategory(ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT), + frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF), fixedTransformHint(ui::Transform::ROT_INVALID), autoRefresh(false), isTrustedOverlay(false), @@ -160,6 +161,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeByte, changeFrameRateStrategy); SAFE_PARCEL(output.writeByte, defaultFrameRateCompatibility); SAFE_PARCEL(output.writeByte, frameRateCategory); + SAFE_PARCEL(output.writeByte, frameRateSelectionStrategy); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeBool, autoRefresh); SAFE_PARCEL(output.writeBool, dimmingEnabled); @@ -293,6 +295,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readByte, &changeFrameRateStrategy); SAFE_PARCEL(input.readByte, &defaultFrameRateCompatibility); SAFE_PARCEL(input.readByte, &frameRateCategory); + SAFE_PARCEL(input.readByte, &frameRateSelectionStrategy); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readBool, &autoRefresh); @@ -666,6 +669,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFrameRateCategoryChanged; frameRateCategory = other.frameRateCategory; } + if (other.what & eFrameRateSelectionStrategyChanged) { + what |= eFrameRateSelectionStrategyChanged; + frameRateSelectionStrategy = other.frameRateSelectionStrategy; + } if (other.what & eFixedTransformHintChanged) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; @@ -777,6 +784,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF3(diff, eFrameRateChanged, other, frameRate, frameRateCompatibility, changeFrameRateStrategy); CHECK_DIFF(diff, eFrameRateCategoryChanged, other, frameRateCategory); + CHECK_DIFF(diff, eFrameRateSelectionStrategyChanged, other, frameRateSelectionStrategy); CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint); CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh); CHECK_DIFF(diff, eTrustedOverlayChanged, other, isTrustedOverlay); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4db960e7fa..c2543d182b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2104,6 +2104,19 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame return *this; } +SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::setFrameRateSelectionStrategy(const sp& sc, + int8_t strategy) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameRateSelectionStrategyChanged; + s->frameRateSelectionStrategy = strategy; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixedTransformHint( const sp& sc, int32_t fixedTransformHint) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 8c360589f0..35fcccdf78 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -197,7 +197,7 @@ struct layer_state_t { eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, eDestinationFrameChanged = 0x1'00000000, - /* unused = 0x2'00000000, */ + eFrameRateSelectionStrategyChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, eColorSpaceAgnosticChanged = 0x10'00000000, @@ -268,6 +268,7 @@ struct layer_state_t { layer_state_t::eColorTransformChanged | layer_state_t::eCornerRadiusChanged | layer_state_t::eFlagsChanged | layer_state_t::eTrustedOverlayChanged | layer_state_t::eFrameRateChanged | layer_state_t::eFrameRateCategoryChanged | + layer_state_t::eFrameRateSelectionStrategyChanged | layer_state_t::eFrameRateSelectionPriority | layer_state_t::eFixedTransformHintChanged; // Changes affecting data sent to input. @@ -361,6 +362,9 @@ struct layer_state_t { // Frame rate category to suggest what frame rate range a surface should run. int8_t frameRateCategory; + // Strategy of the layer for frame rate selection. + int8_t frameRateSelectionStrategy; + // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that // the graphic producers should receive a transform hint as if the diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6fef5d2378..42e3c164ed 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -687,6 +687,8 @@ public: Transaction& setFrameRateCategory(const sp& sc, int8_t category); + Transaction& setFrameRateSelectionStrategy(const sp& sc, int8_t strategy); + // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that // the graphic producers should receive a transform hint as if the diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index e158f01e8c..b068f4807c 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1096,6 +1096,26 @@ enum { ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH = 4 }; +/* + * Frame rate selection strategy values that can be used in + * Transaction::setFrameRateSelectionStrategy. + */ +enum { + /** + * Default value. The layer uses its own frame rate specifications, assuming it has any + * specifications, instead of its parent's. + */ + ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF = 0, + + /** + * The layer's frame rate specifications will propagate to and override those of its descendant + * layers. + * The layer with this strategy has the ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF + * behavior for itself. + */ + ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN = 1, +}; + static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy) { return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index 7537a39060..a5e9368565 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -85,6 +85,7 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { bool isTrustedOverlay; gui::GameMode gameMode; scheduler::LayerInfo::FrameRate frameRate; + scheduler::LayerInfo::FrameRateSelectionStrategy frameRateSelectionStrategy; ui::Transform::RotationFlags fixedTransformHint; std::optional transformHint; bool handleSkipScreenshotFlag = false; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index da84e44085..4c9fb0655b 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -813,11 +813,23 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a RequestedLayerState::Changes::Hierarchy) || snapshot.changes.any(RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::Hierarchy)) { - snapshot.frameRate = requested.requestedFrameRate.isValid() ? requested.requestedFrameRate - : parentSnapshot.frameRate; + bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy == + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren; + snapshot.frameRate = !requested.requestedFrameRate.isValid() || shouldOverrideChildren + ? parentSnapshot.frameRate + : requested.requestedFrameRate; snapshot.changes |= RequestedLayerState::Changes::FrameRate; } + if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionStrategyChanged) { + const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy( + requested.frameRateSelectionStrategy); + snapshot.frameRateSelectionStrategy = + strategy == scheduler::LayerInfo::FrameRateSelectionStrategy::Self + ? parentSnapshot.frameRateSelectionStrategy + : strategy; + } + if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) { snapshot.frameRateSelectionPriority = (requested.frameRateSelectionPriority == Layer::PRIORITY_UNSET) diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 57ebee92d4..acec630167 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -125,6 +125,8 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) defaultFrameRateCompatibility = static_cast(scheduler::LayerInfo::FrameRateCompatibility::Default); frameRateCategory = static_cast(FrameRateCategory::Default); + frameRateSelectionStrategy = + static_cast(scheduler::LayerInfo::FrameRateSelectionStrategy::Self); dataspace = ui::Dataspace::V0_SRGB; gameMode = gui::GameMode::Unsupported; requestedFrameRate = {}; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 26840005d4..31b5e28e4e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -192,6 +192,7 @@ Layer::Layer(const surfaceflinger::LayerCreationArgs& args) mDrawingState.dropInputMode = gui::DropInputMode::NONE; mDrawingState.dimmingEnabled = true; mDrawingState.defaultFrameRateCompatibility = FrameRateCompatibility::Default; + mDrawingState.frameRateSelectionStrategy = FrameRateSelectionStrategy::Self; if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. @@ -1338,6 +1339,15 @@ bool Layer::setFrameRateCategory(FrameRateCategory category) { return true; } +bool Layer::setFrameRateSelectionStrategy(FrameRateSelectionStrategy strategy) { + if (mDrawingState.frameRateSelectionStrategy == strategy) return false; + mDrawingState.frameRateSelectionStrategy = strategy; + mDrawingState.sequence++; + mDrawingState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { mDrawingState.postTime = postTime; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0b0cef54bf..d5e2185a5e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -112,6 +112,7 @@ public: using FrameRate = scheduler::LayerInfo::FrameRate; using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility; + using FrameRateSelectionStrategy = scheduler::LayerInfo::FrameRateSelectionStrategy; struct State { int32_t z; @@ -188,6 +189,8 @@ public: // The combined frame rate of parents / children of this layer FrameRate frameRateForLayerTree; + FrameRateSelectionStrategy frameRateSelectionStrategy; + // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that // the graphic producers should receive a transform hint as if the @@ -782,6 +785,8 @@ public: bool setFrameRate(FrameRate::FrameRateVote); bool setFrameRateCategory(FrameRateCategory); + bool setFrameRateSelectionStrategy(FrameRateSelectionStrategy); + virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime); void setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 0784251dc6..03844ef183 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -490,6 +490,19 @@ FrameRateCategory LayerInfo::FrameRate::convertCategory(int8_t category) { } } +LayerInfo::FrameRateSelectionStrategy LayerInfo::convertFrameRateSelectionStrategy( + int8_t strategy) { + switch (strategy) { + case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF: + return FrameRateSelectionStrategy::Self; + case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN: + return FrameRateSelectionStrategy::OverrideChildren; + default: + LOG_ALWAYS_FATAL("Invalid frame rate selection strategy value %d", strategy); + return FrameRateSelectionStrategy::Self; + } +} + bool LayerInfo::FrameRate::isNoVote() const { return vote.type == FrameRateCompatibility::NoVote; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 7fe407f5f7..3b4d8239d2 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -96,6 +96,13 @@ public: ftl_last = NoVote }; + enum class FrameRateSelectionStrategy { + Self, + OverrideChildren, + + ftl_last = OverrideChildren + }; + // Encapsulates the frame rate specifications of the layer. This information will be used // when the display refresh rate is determined. struct FrameRate { @@ -139,11 +146,11 @@ public: static FrameRateCompatibility convertCompatibility(int8_t compatibility); // Convert an ANATIVEWINDOW_CHANGE_FRAME_RATE_* value to a scheduler::Seamlessness. - // Logs fatal if the compatibility value is invalid. + // Logs fatal if the strategy value is invalid. static scheduler::Seamlessness convertChangeFrameRateStrategy(int8_t strategy); // Convert an ANATIVEWINDOW_FRAME_RATE_CATEGORY_* value to a FrameRateCategory. - // Logs fatal if the compatibility value is invalid. + // Logs fatal if the category value is invalid. static FrameRateCategory convertCategory(int8_t category); // True if the FrameRate has explicit frame rate specifications. @@ -164,6 +171,10 @@ public: } }; + // Convert an ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_* value to FrameRateSelectionStrategy. + // Logs fatal if the strategy value is invalid. + static FrameRateSelectionStrategy convertFrameRateSelectionStrategy(int8_t strategy); + static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; } LayerInfo(const std::string& name, uid_t ownerUid, LayerHistory::LayerVoteType defaultVote); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6d4d186fd7..10768a9b0c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5206,6 +5206,14 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime flags |= eTraversalNeeded; } } + if (what & layer_state_t::eFrameRateSelectionStrategyChanged) { + const scheduler::LayerInfo::FrameRateSelectionStrategy strategy = + scheduler::LayerInfo::convertFrameRateSelectionStrategy( + s.frameRateSelectionStrategy); + if (layer->setFrameRateSelectionStrategy(strategy)) { + flags |= eTraversalNeeded; + } + } if (what & layer_state_t::eFixedTransformHintChanged) { if (layer->setFixedTransformHint(s.fixedTransformHint)) { flags |= eTraversalNeeded | eTransformHintUpdateNeeded; diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h index ff644ba9f1..32821b7891 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h @@ -346,6 +346,18 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setFrameRateSelectionStrategy(uint32_t id, int8_t strategy) { + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = + layer_state_t::eFrameRateSelectionStrategyChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.frameRateSelectionStrategy = strategy; + mLifecycleManager.applyTransactions(transactions); + } + void setRoundedCorners(uint32_t id, float radius) { std::vector transactions; transactions.emplace_back(); diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 1227b994dd..662f4bd466 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -743,6 +743,50 @@ TEST_F(LayerSnapshotTest, frameRateWithCategory) { EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); } +TEST_F(LayerSnapshotTest, frameRateSelectionStrategy) { + // ROOT + // ├── 1 + // │ ├── 11 + // │ │ └── 111 + // │ ├── 12 (frame rate set to 244.f with strategy OverrideChildren) + // │ │ ├── 121 + // │ │ └── 122 (frame rate set to 123.f but should be overridden by layer 12) + // │ │ └── 1221 + // │ └── 13 + // └── 2 + setFrameRate(12, 244.f, 0, 0); + setFrameRate(122, 123.f, 0, 0); + setFrameRateSelectionStrategy(12, 1 /* OverrideChildren */); + + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + // verify parent 1 gets no vote + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, + scheduler::LayerInfo::FrameRateCompatibility::NoVote); + EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify layer 12 and all descendants (121, 122, 1221) get the requested vote + EXPECT_EQ(getSnapshot({.id = 12})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 12})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 121})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 121})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 121})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 122})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 1221})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); +} + TEST_F(LayerSnapshotTest, skipRoundCornersWhenProtected) { setRoundedCorners(1, 42.f); setRoundedCorners(2, 42.f); -- cgit v1.2.3-59-g8ed1b From 0faad6c29ae2e62abd8b18e3438d891961c15150 Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Fri, 8 Sep 2023 13:34:34 -0700 Subject: Logic for setFrameRateSelectionStrategy. Use the frameRateSelectionStrategy value stored in Layer to inform the frame rate propagation in the hierarchy. Bug: 297418260 Test: atest CtsSurfaceControlTestsStaging Test: atest libsurfaceflinger_unittest Change-Id: I05a6a7effd17cefb01421bff10c9ff9dbcadf98a --- services/surfaceflinger/Layer.cpp | 16 ++- services/surfaceflinger/Layer.h | 8 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../unittests/FrameRateSelectionStrategyTest.cpp | 159 +++++++++++++++++++++ 4 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 31b5e28e4e..e780a1e8f7 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1252,9 +1252,14 @@ const half4& Layer::getBorderColor() { return mBorderColor; } -bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded) { - // The frame rate for layer tree is this layer's frame rate if present, or the parent frame rate +bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren, + bool* transactionNeeded) { + // Gets the frame rate to propagate to children. const auto frameRate = [&] { + if (overrideChildren && parentFrameRate.isValid()) { + return parentFrameRate; + } + if (mDrawingState.frameRate.isValid()) { return mDrawingState.frameRate; } @@ -1268,7 +1273,10 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran bool childrenHaveFrameRate = false; for (const sp& child : mCurrentChildren) { childrenHaveFrameRate |= - child->propagateFrameRateForLayerTree(frameRate, transactionNeeded); + child->propagateFrameRateForLayerTree(frameRate, + overrideChildren || + shouldOverrideChildrenFrameRate(), + transactionNeeded); } // If we don't have a valid frame rate specification, but the children do, we set this @@ -1301,7 +1309,7 @@ void Layer::updateTreeHasFrameRateVote() { }(); bool transactionNeeded = false; - root->propagateFrameRateForLayerTree({}, &transactionNeeded); + root->propagateFrameRateForLayerTree({}, false, &transactionNeeded); // TODO(b/195668952): we probably don't need eTraversalNeeded here if (transactionNeeded) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d5e2185a5e..40882f442c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1102,7 +1102,8 @@ private: const std::vector& layersInTree); void updateTreeHasFrameRateVote(); - bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded); + bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren, + bool* transactionNeeded); void setZOrderRelativeOf(const wp& relativeOf); bool isTrustedOverlay() const; gui::DropInputMode getDropInputMode() const; @@ -1164,6 +1165,11 @@ private: void transferAvailableJankData(const std::deque>& handles, std::vector& jankData); + bool shouldOverrideChildrenFrameRate() const { + return getDrawingState().frameRateSelectionStrategy == + FrameRateSelectionStrategy::OverrideChildren; + } + // Cached properties computed from drawing state // Effective transform taking into account parent transforms and any parent scaling, which is // a transform from the current layer coordinate space to display(screen) coordinate space. diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 8deff85118..f4516c7635 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -87,6 +87,7 @@ cc_test { "FramebufferSurfaceTest.cpp", "FrameRateOverrideMappingsTest.cpp", "FrameRateSelectionPriorityTest.cpp", + "FrameRateSelectionStrategyTest.cpp", "FrameTimelineTest.cpp", "GameModeTest.cpp", "HWComposerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp new file mode 100644 index 0000000000..ffe6f245b5 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp @@ -0,0 +1,159 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include +#include + +#include "Layer.h" +#include "LayerTestUtils.h" +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" + +namespace android { + +using testing::DoAll; +using testing::Mock; +using testing::SetArgPointee; + +using android::Hwc2::IComposer; +using android::Hwc2::IComposerClient; + +using scheduler::LayerHistory; + +using FrameRate = Layer::FrameRate; +using FrameRateCompatibility = Layer::FrameRateCompatibility; +using FrameRateSelectionStrategy = scheduler::LayerInfo::FrameRateSelectionStrategy; + +/** + * This class tests the behaviour of Layer::setFrameRateSelectionStrategy. + */ +class FrameRateSelectionStrategyTest : public BaseLayerTest { +protected: + const FrameRate FRAME_RATE_VOTE1 = FrameRate(11_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE2 = FrameRate(22_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE3 = FrameRate(33_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_TREE = FrameRate(Fps(), FrameRateCompatibility::NoVote); + + FrameRateSelectionStrategyTest(); + + void addChild(sp layer, sp child); + void removeChild(sp layer, sp child); + void commitTransaction(); + + std::vector> mLayers; +}; + +FrameRateSelectionStrategyTest::FrameRateSelectionStrategyTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + mFlinger.setupComposer(std::make_unique()); +} + +void FrameRateSelectionStrategyTest::addChild(sp layer, sp child) { + layer->addChild(child); +} + +void FrameRateSelectionStrategyTest::removeChild(sp layer, sp child) { + layer->removeChild(child); +} + +void FrameRateSelectionStrategyTest::commitTransaction() { + for (auto layer : mLayers) { + layer->commitTransaction(); + } +} + +namespace { + +INSTANTIATE_TEST_SUITE_P(PerLayerType, FrameRateSelectionStrategyTest, + testing::Values(std::make_shared(), + std::make_shared()), + PrintToStringParamName); + +TEST_P(FrameRateSelectionStrategyTest, SetAndGet) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto layer = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + layer->setFrameRate(FRAME_RATE_VOTE1.vote); + layer->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + commitTransaction(); + EXPECT_EQ(FRAME_RATE_VOTE1, layer->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer->getDrawingState().frameRateSelectionStrategy); +} + +TEST_P(FrameRateSelectionStrategyTest, SetChildAndGetParent) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + addChild(parent, child1); + addChild(child1, child2); + + child2->setFrameRate(FRAME_RATE_VOTE1.vote); + child2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + commitTransaction(); + EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + parent->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + child1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + child2->getDrawingState().frameRateSelectionStrategy); +} + +TEST_P(FrameRateSelectionStrategyTest, SetParentAndGet) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto layer1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto layer2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto layer3 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + addChild(layer1, layer2); + addChild(layer2, layer3); + + layer1->setFrameRate(FRAME_RATE_VOTE1.vote); + layer1->setFrameRate(FRAME_RATE_VOTE1.vote); + layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + layer2->setFrameRate(FRAME_RATE_VOTE2.vote); + layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + layer3->setFrameRate(FRAME_RATE_VOTE3.vote); + commitTransaction(); + + EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, layer2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer2->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer3->getDrawingState().frameRateSelectionStrategy); +} + +} // namespace +} // namespace android \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From d7479506dcbf82d9fc01c512fbe18c8c5d979254 Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Mon, 25 Sep 2023 17:02:35 -0700 Subject: Propagate tree on setting selection strategy Otherwise there is an order dependency on calling setFrameRate, setFrameRateCategory, and setFrameRateSelectionStrategy. Bug: 297418260 Test: atest FrameRateSelectionStrategyTest Change-Id: I9fb345a1632c5a18fe445d1637b6bb22984fe24e --- services/surfaceflinger/Layer.cpp | 2 ++ .../tests/unittests/FrameRateSelectionStrategyTest.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e780a1e8f7..a73c5115b1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1352,6 +1352,8 @@ bool Layer::setFrameRateSelectionStrategy(FrameRateSelectionStrategy strategy) { mDrawingState.frameRateSelectionStrategy = strategy; mDrawingState.sequence++; mDrawingState.modified = true; + + updateTreeHasFrameRateVote(); setTransactionFlags(eTransactionNeeded); return true; } diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp index ffe6f245b5..20ea0c080a 100644 --- a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp @@ -153,6 +153,19 @@ TEST_P(FrameRateSelectionStrategyTest, SetParentAndGet) { EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); EXPECT_EQ(FrameRateSelectionStrategy::Self, layer3->getDrawingState().frameRateSelectionStrategy); + + layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::Self); + commitTransaction(); + + EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer2->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE2, layer3->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer3->getDrawingState().frameRateSelectionStrategy); } } // namespace -- cgit v1.2.3-59-g8ed1b From 66ed1c48f6a9a152576edb98472bfe1cae1324df Mon Sep 17 00:00:00 2001 From: Dorin Drimus Date: Wed, 27 Sep 2023 13:10:16 +0000 Subject: Properly release the sideband stream when setting a buffer Bug: 301910615 Change-Id: I0dfdb5bb6816be5227a7d6b720654bd722438ffd Test: Netflix playback changing streams --- services/surfaceflinger/Layer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a73c5115b1..5890050caa 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3183,8 +3183,7 @@ bool Layer::setBuffer(std::shared_ptr& buffer, } else { // release sideband stream if it exists and a non null buffer is being set if (mDrawingState.sidebandStream != nullptr) { - mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount(); - mDrawingState.sidebandStream = nullptr; + setSidebandStream(nullptr, info, postTime); } } -- cgit v1.2.3-59-g8ed1b From 3fbe326861bc22e40847b9edf3e905f4bd41d645 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 29 Sep 2023 17:07:00 -0700 Subject: Pull out FrameRateCompatibility definition to avoid circular dependencies Test: presubmit Bug: 300701739 Change-Id: I7a1cc64a786fca5a7a273522dc4735439b44fd13 --- .../FrontEnd/LayerSnapshotBuilder.cpp | 2 +- .../FrontEnd/RequestedLayerState.cpp | 3 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 2 +- .../Scheduler/FrameRateCompatibility.h | 38 +++++++++++++++ services/surfaceflinger/Scheduler/LayerHistory.cpp | 6 +-- services/surfaceflinger/Scheduler/LayerInfo.cpp | 2 +- services/surfaceflinger/Scheduler/LayerInfo.h | 19 +------- .../tests/unittests/LayerHistoryTest.cpp | 4 +- .../tests/unittests/LayerSnapshotTest.cpp | 57 ++++++++++------------ .../tests/unittests/mock/MockLayer.h | 5 +- 11 files changed, 78 insertions(+), 62 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/FrameRateCompatibility.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 4c9fb0655b..55be398bd0 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -666,7 +666,7 @@ void LayerSnapshotBuilder::updateFrameRateFromChildSnapshot(LayerSnapshot& snaps return; } - using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility; + using FrameRateCompatibility = scheduler::FrameRateCompatibility; if (snapshot.frameRate.isValid()) { // we already have a valid framerate. return; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index fcc1e61c95..a4c7852801 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -122,8 +122,7 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) isTrustedOverlay = false; dropInputMode = gui::DropInputMode::NONE; dimmingEnabled = true; - defaultFrameRateCompatibility = - static_cast(scheduler::LayerInfo::FrameRateCompatibility::Default); + defaultFrameRateCompatibility = static_cast(scheduler::FrameRateCompatibility::Default); frameRateCategory = static_cast(FrameRateCategory::Default); frameRateSelectionStrategy = static_cast(scheduler::LayerInfo::FrameRateSelectionStrategy::Self); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 31b5e28e4e..cbed0e7a98 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1160,7 +1160,7 @@ bool Layer::setDefaultFrameRateCompatibility(FrameRateCompatibility compatibilit return true; } -scheduler::LayerInfo::FrameRateCompatibility Layer::getDefaultFrameRateCompatibility() const { +scheduler::FrameRateCompatibility Layer::getDefaultFrameRateCompatibility() const { return mDrawingState.defaultFrameRateCompatibility; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d5e2185a5e..dbde96f115 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -111,7 +111,7 @@ public: }; using FrameRate = scheduler::LayerInfo::FrameRate; - using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility; + using FrameRateCompatibility = scheduler::FrameRateCompatibility; using FrameRateSelectionStrategy = scheduler::LayerInfo::FrameRateSelectionStrategy; struct State { diff --git a/services/surfaceflinger/Scheduler/FrameRateCompatibility.h b/services/surfaceflinger/Scheduler/FrameRateCompatibility.h new file mode 100644 index 0000000000..405c982494 --- /dev/null +++ b/services/surfaceflinger/Scheduler/FrameRateCompatibility.h @@ -0,0 +1,38 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace android::scheduler { +// FrameRateCompatibility specifies how we should interpret the frame rate associated with +// the layer. +enum class FrameRateCompatibility { + Default, // Layer didn't specify any specific handling strategy + + Min, // Layer needs the minimum frame rate. + + Exact, // Layer needs the exact frame rate. + + ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the + // content properly. Any other value will result in a pull down. + + NoVote, // Layer doesn't have any requirements for the refresh rate and + // should not be considered when the display refresh rate is determined. + + ftl_last = NoVote +}; + +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 6b5327aa64..b98b8007ac 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -76,12 +76,12 @@ void trace(const LayerInfo& info, LayerHistory::LayerVoteType type, int fps) { ALOGD("%s: %s @ %d Hz", __FUNCTION__, info.getName().c_str(), fps); } -LayerHistory::LayerVoteType getVoteType(LayerInfo::FrameRateCompatibility compatibility, +LayerHistory::LayerVoteType getVoteType(FrameRateCompatibility compatibility, bool contentDetectionEnabled) { LayerHistory::LayerVoteType voteType; - if (!contentDetectionEnabled || compatibility == LayerInfo::FrameRateCompatibility::NoVote) { + if (!contentDetectionEnabled || compatibility == FrameRateCompatibility::NoVote) { voteType = LayerHistory::LayerVoteType::NoVote; - } else if (compatibility == LayerInfo::FrameRateCompatibility::Min) { + } else if (compatibility == FrameRateCompatibility::Min) { voteType = LayerHistory::LayerVoteType::Min; } else { voteType = LayerHistory::LayerVoteType::Heuristic; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 875bdc84f5..dd96930a06 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -455,7 +455,7 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const { return consistent; } -LayerInfo::FrameRateCompatibility LayerInfo::FrameRate::convertCompatibility(int8_t compatibility) { +FrameRateCompatibility LayerInfo::FrameRate::convertCompatibility(int8_t compatibility) { switch (compatibility) { case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT: return FrameRateCompatibility::Default; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 129b4c44d4..6286b285cf 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -28,6 +28,7 @@ #include #include +#include "FrameRateCompatibility.h" #include "LayerHistory.h" #include "RefreshRateSelector.h" @@ -78,24 +79,6 @@ public: using RefreshRateVotes = ftl::SmallVector; - // FrameRateCompatibility specifies how we should interpret the frame rate associated with - // the layer. - enum class FrameRateCompatibility { - Default, // Layer didn't specify any specific handling strategy - - Min, // Layer needs the minimum frame rate. - - Exact, // Layer needs the exact frame rate. - - ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the - // content properly. Any other value will result in a pull down. - - NoVote, // Layer doesn't have any requirements for the refresh rate and - // should not be considered when the display refresh rate is determined. - - ftl_last = NoVote - }; - enum class FrameRateSelectionStrategy { Self, OverrideChildren, diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 7e3e61f6fb..cc7a45c78f 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -152,7 +152,7 @@ TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) { EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_CALL(*layer, getDefaultFrameRateCompatibility()) - .WillOnce(Return(LayerInfo::FrameRateCompatibility::NoVote)); + .WillOnce(Return(FrameRateCompatibility::NoVote)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -176,7 +176,7 @@ TEST_F(LayerHistoryTest, singleLayerMinVoteDefaultCompatibility) { EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); EXPECT_CALL(*layer, getDefaultFrameRateCompatibility()) - .WillOnce(Return(LayerInfo::FrameRateCompatibility::Min)); + .WillOnce(Return(FrameRateCompatibility::Min)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 1a9233d12c..69316bf4e5 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -315,14 +315,11 @@ TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) { UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); EXPECT_EQ(getSnapshot(11)->frameRate.vote.rate.getIntValue(), 90); - EXPECT_EQ(getSnapshot(11)->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Exact); + EXPECT_EQ(getSnapshot(11)->frameRate.vote.type, scheduler::FrameRateCompatibility::Exact); EXPECT_EQ(getSnapshot(111)->frameRate.vote.rate.getIntValue(), 90); - EXPECT_EQ(getSnapshot(111)->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Exact); + EXPECT_EQ(getSnapshot(111)->frameRate.vote.type, scheduler::FrameRateCompatibility::Exact); EXPECT_EQ(getSnapshot(1)->frameRate.vote.rate.getIntValue(), 0); - EXPECT_EQ(getSnapshot(1)->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + EXPECT_EQ(getSnapshot(1)->frameRate.vote.type, scheduler::FrameRateCompatibility::NoVote); } TEST_F(LayerSnapshotTest, CanCropTouchableRegion) { @@ -550,20 +547,20 @@ TEST_F(LayerSnapshotTest, framerate) { // verify parent is gets no vote EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer and children get the requested votes EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); // reparent and verify the child gets the new parent's framerate @@ -574,23 +571,23 @@ TEST_F(LayerSnapshotTest, framerate) { // verify parent is gets no vote EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); // verify layer and children get the requested votes EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); // reparent and verify the new parent gets no vote @@ -601,30 +598,30 @@ TEST_F(LayerSnapshotTest, framerate) { // verify old parent has invalid framerate (default) EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify new parent get no vote EXPECT_FALSE(getSnapshot({.id = 2})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 2})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 2})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer and children get the requested votes (unchanged) EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); } TEST_F(LayerSnapshotTest, translateDataspace) { @@ -653,33 +650,33 @@ TEST_F(LayerSnapshotTest, frameRateWithCategory) { // verify parent 1 gets no vote EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer 11 and children 111 get the requested votes EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify parent 12 gets no vote EXPECT_FALSE(getSnapshot({.id = 12})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 12})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer 122 and children 1221 get the requested votes EXPECT_FALSE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.isValid()); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.category, FrameRateCategory::Normal); EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_TRUE( @@ -688,7 +685,7 @@ TEST_F(LayerSnapshotTest, frameRateWithCategory) { EXPECT_FALSE(getSnapshot({.id = 1221})->frameRate.vote.rate.isValid()); EXPECT_TRUE(getSnapshot({.id = 1221})->frameRate.isValid()); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.category, FrameRateCategory::Normal); EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_TRUE( @@ -713,32 +710,32 @@ TEST_F(LayerSnapshotTest, frameRateWithCategory) { // verify parent is gets no vote EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); // verify layer 11 and children 111 get the requested votes EXPECT_TRUE(getSnapshot({.id = 11})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); // verify layer 122 and children 1221 get the requested category vote (unchanged from // reparenting) EXPECT_FALSE(getSnapshot({.id = 122})->frameRate.vote.rate.isValid()); EXPECT_TRUE(getSnapshot({.id = 122})->frameRate.isValid()); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.category, FrameRateCategory::Normal); EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_FALSE(getSnapshot({.id = 1221})->frameRate.vote.rate.isValid()); EXPECT_TRUE(getSnapshot({.id = 1221})->frameRate.isValid()); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::Default); + scheduler::FrameRateCompatibility::Default); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.category, FrameRateCategory::Normal); EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); } @@ -762,7 +759,7 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategy) { // verify parent 1 gets no vote EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, - scheduler::LayerInfo::FrameRateCompatibility::NoVote); + scheduler::FrameRateCompatibility::NoVote); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer 12 and all descendants (121, 122, 1221) get the requested vote diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index 50e07fc92c..4cc78febee 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -25,7 +25,7 @@ public: MockLayer(SurfaceFlinger* flinger, std::string name) : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) { EXPECT_CALL(*this, getDefaultFrameRateCompatibility()) - .WillOnce(testing::Return(scheduler::LayerInfo::FrameRateCompatibility::Default)); + .WillOnce(testing::Return(scheduler::FrameRateCompatibility::Default)); } explicit MockLayer(SurfaceFlinger* flinger) : MockLayer(flinger, "TestLayer") {} @@ -34,8 +34,7 @@ public: MOCK_CONST_METHOD0(isVisible, bool()); MOCK_METHOD1(createClone, sp(uint32_t)); MOCK_CONST_METHOD0(getFrameRateForLayerTree, FrameRate()); - MOCK_CONST_METHOD0(getDefaultFrameRateCompatibility, - scheduler::LayerInfo::FrameRateCompatibility()); + MOCK_CONST_METHOD0(getDefaultFrameRateCompatibility, scheduler::FrameRateCompatibility()); MOCK_CONST_METHOD0(getOwnerUid, uid_t()); MOCK_CONST_METHOD0(getDataSpace, ui::Dataspace()); }; -- cgit v1.2.3-59-g8ed1b From 80e8cfe3d73baecc749dba0de0bd7f96c17a5eec Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 29 Sep 2023 17:03:45 -0700 Subject: [sf-newfe] update default frame rate compatibility Bug: 300701739 Test: presubmit Change-Id: I3dbfd8d7ef6fe801d4d750c1828d09da511ce283 --- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 9 +++++++++ services/surfaceflinger/FrontEnd/LayerSnapshot.h | 2 ++ services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 10 +++++----- services/surfaceflinger/Scheduler/LayerHistory.h | 4 +++- services/surfaceflinger/Scheduler/Scheduler.cpp | 5 +++-- services/surfaceflinger/Scheduler/Scheduler.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 13 +++++++++++-- .../surfaceflinger/tests/unittests/LayerHistoryTest.cpp | 9 +++++++-- 9 files changed, 42 insertions(+), 14 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 899d2dedaf..f9c8e812dd 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -398,6 +398,15 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate geomCrop = requested.crop; } + if (forceUpdate || requested.what & layer_state_t::eDefaultFrameRateCompatibilityChanged) { + const auto compatibility = + Layer::FrameRate::convertCompatibility(requested.defaultFrameRateCompatibility); + if (defaultFrameRateCompatibility != compatibility) { + clientChanges |= layer_state_t::eDefaultFrameRateCompatibilityChanged; + } + defaultFrameRateCompatibility = compatibility; + } + if (forceUpdate || requested.what & (layer_state_t::eFlagsChanged | layer_state_t::eBufferChanged | diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index a5e9368565..a1c72a94e0 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -86,6 +86,8 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { gui::GameMode gameMode; scheduler::LayerInfo::FrameRate frameRate; scheduler::LayerInfo::FrameRateSelectionStrategy frameRateSelectionStrategy; + scheduler::FrameRateCompatibility defaultFrameRateCompatibility = + scheduler::FrameRateCompatibility::Default; ui::Transform::RotationFlags fixedTransformHint; std::optional transformHint; bool handleSkipScreenshotFlag = false; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 415f55ae66..5ae29990dc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1155,7 +1155,7 @@ bool Layer::setDefaultFrameRateCompatibility(FrameRateCompatibility compatibilit if (mDrawingState.defaultFrameRateCompatibility == compatibility) return false; mDrawingState.defaultFrameRateCompatibility = compatibility; mDrawingState.modified = true; - mFlinger->mScheduler->setDefaultFrameRateCompatibility(this); + mFlinger->mScheduler->setDefaultFrameRateCompatibility(sequence, compatibility); setTransactionFlags(eTransactionNeeded); return true; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index b98b8007ac..4e5659ec5a 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -141,20 +141,20 @@ void LayerHistory::record(int32_t id, const LayerProps& layerProps, nsecs_t pres } } -void LayerHistory::setDefaultFrameRateCompatibility(Layer* layer, bool contentDetectionEnabled) { +void LayerHistory::setDefaultFrameRateCompatibility(int32_t id, + FrameRateCompatibility frameRateCompatibility, + bool contentDetectionEnabled) { std::lock_guard lock(mLock); - auto id = layer->getSequence(); auto [found, layerPair] = findLayer(id); if (found == LayerStatus::NotFound) { // Offscreen layer - ALOGV("%s: %s not registered", __func__, layer->getName().c_str()); + ALOGV("%s: %d not registered", __func__, id); return; } const auto& info = layerPair->second; - info->setDefaultLayerVote( - getVoteType(layer->getDefaultFrameRateCompatibility(), contentDetectionEnabled)); + info->setDefaultLayerVote(getVoteType(frameRateCompatibility, contentDetectionEnabled)); } auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) -> Summary { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 5750ea7898..40bda83e62 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -29,6 +29,7 @@ #include "EventThread.h" +#include "FrameRateCompatibility.h" #include "RefreshRateSelector.h" namespace android { @@ -70,7 +71,8 @@ public: // Updates the default frame rate compatibility which takes effect when the app // does not set a preference for refresh rate. - void setDefaultFrameRateCompatibility(Layer*, bool contentDetectionEnabled); + void setDefaultFrameRateCompatibility(int32_t id, FrameRateCompatibility frameRateCompatibility, + bool contentDetectionEnabled); using Summary = std::vector; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 68e2ce9b98..76f1af9f56 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -635,8 +635,9 @@ void Scheduler::setModeChangePending(bool pending) { mLayerHistory.setModeChangePending(pending); } -void Scheduler::setDefaultFrameRateCompatibility(Layer* layer) { - mLayerHistory.setDefaultFrameRateCompatibility(layer, +void Scheduler::setDefaultFrameRateCompatibility( + int32_t id, scheduler::FrameRateCompatibility frameRateCompatibility) { + mLayerHistory.setDefaultFrameRateCompatibility(id, frameRateCompatibility, mFeatures.test(Feature::kContentDetection)); } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index f652bb2627..e6db654637 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -232,7 +232,7 @@ public: void recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime, LayerHistory::LayerUpdateType) EXCLUDES(mDisplayLock); void setModeChangePending(bool pending); - void setDefaultFrameRateCompatibility(Layer*); + void setDefaultFrameRateCompatibility(int32_t id, scheduler::FrameRateCompatibility); void deregisterLayer(Layer*); void onLayerDestroyed(Layer*) EXCLUDES(mChoreographerLock); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3f52444c40..4d8dc94db5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2205,8 +2205,12 @@ bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, nsecs_t frameTi void SurfaceFlinger::updateLayerHistory(const frontend::LayerSnapshot& snapshot) { using Changes = frontend::RequestedLayerState::Changes; - if (snapshot.path.isClone() || - !snapshot.changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation)) { + if (snapshot.path.isClone()) { + return; + } + + if (!snapshot.changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) && + (snapshot.clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) == 0) { return; } @@ -2226,6 +2230,11 @@ void SurfaceFlinger::updateLayerHistory(const frontend::LayerSnapshot& snapshot) it->second->recordLayerHistoryAnimationTx(layerProps); } + if (snapshot.clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) { + mScheduler->setDefaultFrameRateCompatibility(snapshot.sequence, + snapshot.defaultFrameRateCompatibility); + } + if (snapshot.changes.test(Changes::FrameRate)) { it->second->setFrameRateForLayerTree(snapshot.frameRate, layerProps); } diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index cc7a45c78f..549a362af3 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -165,7 +165,10 @@ TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) { history().record(layer->getSequence(), layer->getLayerProps(), 0, time, LayerHistory::LayerUpdateType::Buffer); - history().setDefaultFrameRateCompatibility(layer.get(), true /* contentDetectionEnabled */); + history().setDefaultFrameRateCompatibility(layer->getSequence(), + + layer->getDefaultFrameRateCompatibility(), + true /* contentDetectionEnabled */); EXPECT_TRUE(summarizeLayerHistory(time).empty()); EXPECT_EQ(1, activeLayerCount()); @@ -188,7 +191,9 @@ TEST_F(LayerHistoryTest, singleLayerMinVoteDefaultCompatibility) { history().record(layer->getSequence(), layer->getLayerProps(), 0, time, LayerHistory::LayerUpdateType::Buffer); - history().setDefaultFrameRateCompatibility(layer.get(), true /* contentDetectionEnabled */); + history().setDefaultFrameRateCompatibility(layer->getSequence(), + layer->getDefaultFrameRateCompatibility(), + true /* contentDetectionEnabled */); auto summary = summarizeLayerHistory(time); ASSERT_EQ(1, summarizeLayerHistory(time).size()); -- cgit v1.2.3-59-g8ed1b From 47b7bb433909f45d2ee9de3f576ac97ccad61cb5 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 29 Sep 2023 16:27:33 -0700 Subject: [sf-newfe] Update layer history for invisible layers Fixes a bug with new frontend where we were only updating layer history for layers that has something to draw. Cl also adds integration tests to validate frontend to layerhistory path. Test: LayerHistoryIntegrationTest Fixes: 300701739 Change-Id: I223b4817bdf9909e3890de0b5051bc0ff345f829 --- services/surfaceflinger/Layer.cpp | 25 +- services/surfaceflinger/Layer.h | 8 +- services/surfaceflinger/Scheduler/LayerHistory.h | 1 + services/surfaceflinger/Scheduler/LayerInfo.h | 2 + services/surfaceflinger/Scheduler/Scheduler.cpp | 4 +- services/surfaceflinger/Scheduler/Scheduler.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 70 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/LayerHierarchyTest.h | 71 ++ .../unittests/LayerHistoryIntegrationTest.cpp | 873 +++++++++++++++++++++ .../tests/unittests/LayerHistoryTest.cpp | 2 + .../tests/unittests/LayerSnapshotTest.cpp | 23 +- .../tests/unittests/SchedulerTest.cpp | 6 +- .../tests/unittests/TestableSurfaceFlinger.h | 9 +- 15 files changed, 1021 insertions(+), 78 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5ae29990dc..33d1eeb7cc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1267,7 +1267,8 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overr return parentFrameRate; }(); - *transactionNeeded |= setFrameRateForLayerTreeLegacy(frameRate); + auto now = systemTime(); + *transactionNeeded |= setFrameRateForLayerTreeLegacy(frameRate, now); // The frame rate is propagated to the children bool childrenHaveFrameRate = false; @@ -1283,7 +1284,8 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overr // layer as NoVote to allow the children to control the refresh rate if (!frameRate.isValid() && childrenHaveFrameRate) { *transactionNeeded |= - setFrameRateForLayerTreeLegacy(FrameRate(Fps(), FrameRateCompatibility::NoVote)); + setFrameRateForLayerTreeLegacy(FrameRate(Fps(), FrameRateCompatibility::NoVote), + now); } // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes for @@ -1492,7 +1494,7 @@ void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info, addSurfaceFrameDroppedForBuffer(surfaceFrame, postTime); } -bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate) { +bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate, nsecs_t now) { if (mDrawingState.frameRateForLayerTree == frameRate) { return false; } @@ -1506,19 +1508,20 @@ bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate) { setTransactionFlags(eTransactionNeeded); mFlinger->mScheduler - ->recordLayerHistory(sequence, getLayerProps(), systemTime(), + ->recordLayerHistory(sequence, getLayerProps(), now, now, scheduler::LayerHistory::LayerUpdateType::SetFrameRate); return true; } -bool Layer::setFrameRateForLayerTree(FrameRate frameRate, const scheduler::LayerProps& layerProps) { +bool Layer::setFrameRateForLayerTree(FrameRate frameRate, const scheduler::LayerProps& layerProps, + nsecs_t now) { if (mDrawingState.frameRateForLayerTree == frameRate) { return false; } mDrawingState.frameRateForLayerTree = frameRate; mFlinger->mScheduler - ->recordLayerHistory(sequence, layerProps, systemTime(), + ->recordLayerHistory(sequence, layerProps, now, now, scheduler::LayerHistory::LayerUpdateType::SetFrameRate); return true; } @@ -3225,7 +3228,7 @@ bool Layer::setBuffer(std::shared_ptr& buffer, mOwnerUid, postTime, getGameMode()); if (mFlinger->mLegacyFrontEndEnabled) { - recordLayerHistoryBufferUpdate(getLayerProps()); + recordLayerHistoryBufferUpdate(getLayerProps(), systemTime()); } setFrameTimelineVsyncForBufferTransaction(info, postTime); @@ -3256,7 +3259,7 @@ void Layer::setDesiredPresentTime(nsecs_t desiredPresentTime, bool isAutoTimesta mDrawingState.isAutoTimestamp = isAutoTimestamp; } -void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps) { +void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps, nsecs_t now) { ATRACE_CALL(); const nsecs_t presentTime = [&] { if (!mDrawingState.isAutoTimestamp) { @@ -3310,14 +3313,14 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro ATRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str()); } - mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, + mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now, scheduler::LayerHistory::LayerUpdateType::Buffer); } -void Layer::recordLayerHistoryAnimationTx(const scheduler::LayerProps& layerProps) { +void Layer::recordLayerHistoryAnimationTx(const scheduler::LayerProps& layerProps, nsecs_t now) { const nsecs_t presentTime = mDrawingState.isAutoTimestamp ? 0 : mDrawingState.desiredPresentTime; - mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, + mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now, scheduler::LayerHistory::LayerUpdateType::AnimationTX); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 78a3a7cd5c..0b66866158 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -908,10 +908,10 @@ public: void callReleaseBufferCallback(const sp& listener, const sp& buffer, uint64_t framenumber, const sp& releaseFence); - bool setFrameRateForLayerTreeLegacy(FrameRate); - bool setFrameRateForLayerTree(FrameRate, const scheduler::LayerProps&); - void recordLayerHistoryBufferUpdate(const scheduler::LayerProps&); - void recordLayerHistoryAnimationTx(const scheduler::LayerProps&); + bool setFrameRateForLayerTreeLegacy(FrameRate, nsecs_t now); + bool setFrameRateForLayerTree(FrameRate, const scheduler::LayerProps&, nsecs_t now); + void recordLayerHistoryBufferUpdate(const scheduler::LayerProps&, nsecs_t now); + void recordLayerHistoryAnimationTx(const scheduler::LayerProps&, nsecs_t now); auto getLayerProps() const { return scheduler::LayerProps{ .visible = isVisible(), diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 40bda83e62..bac1ec639a 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -91,6 +91,7 @@ public: private: friend class LayerHistoryTest; + friend class LayerHistoryIntegrationTest; friend class TestableScheduler; using LayerPair = std::pair>; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 6286b285cf..d580b58f53 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -62,6 +62,7 @@ class LayerInfo { static constexpr size_t kNumSmallDirtyThreshold = 2; friend class LayerHistoryTest; + friend class LayerHistoryIntegrationTest; friend class LayerInfoTest; public: @@ -264,6 +265,7 @@ private: private: friend class LayerHistoryTest; + friend class LayerHistoryIntegrationTest; // Holds the refresh rate when it was calculated struct RefreshRateData { diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 76f1af9f56..daf9898d11 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -625,9 +625,9 @@ void Scheduler::onLayerDestroyed(Layer* layer) { } void Scheduler::recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime, - LayerHistory::LayerUpdateType updateType) { + nsecs_t now, LayerHistory::LayerUpdateType updateType) { if (pacesetterSelectorPtr()->canSwitch()) { - mLayerHistory.record(id, layerProps, presentTime, systemTime(), updateType); + mLayerHistory.record(id, layerProps, presentTime, now, updateType); } } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index e6db654637..3441318cd0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -230,7 +230,7 @@ public: // Layers are registered on creation, and unregistered when the weak reference expires. void registerLayer(Layer*); void recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime, - LayerHistory::LayerUpdateType) EXCLUDES(mDisplayLock); + nsecs_t now, LayerHistory::LayerUpdateType) EXCLUDES(mDisplayLock); void setModeChangePending(bool pending); void setDefaultFrameRateCompatibility(int32_t id, scheduler::FrameRateCompatibility); void deregisterLayer(Layer*); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4d8dc94db5..e32e0fd483 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2203,44 +2203,46 @@ bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, nsecs_t frameTi return mustComposite; } -void SurfaceFlinger::updateLayerHistory(const frontend::LayerSnapshot& snapshot) { - using Changes = frontend::RequestedLayerState::Changes; - if (snapshot.path.isClone()) { - return; - } +void SurfaceFlinger::updateLayerHistory(nsecs_t now) { + for (const auto& snapshot : mLayerSnapshotBuilder.getSnapshots()) { + using Changes = frontend::RequestedLayerState::Changes; + if (snapshot->path.isClone()) { + continue; + } - if (!snapshot.changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) && - (snapshot.clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) == 0) { - return; - } + if (!snapshot->changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) && + (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) == 0) { + continue; + } - const auto layerProps = scheduler::LayerProps{ - .visible = snapshot.isVisible, - .bounds = snapshot.geomLayerBounds, - .transform = snapshot.geomLayerTransform, - .setFrameRateVote = snapshot.frameRate, - .frameRateSelectionPriority = snapshot.frameRateSelectionPriority, - }; + const auto layerProps = scheduler::LayerProps{ + .visible = snapshot->isVisible, + .bounds = snapshot->geomLayerBounds, + .transform = snapshot->geomLayerTransform, + .setFrameRateVote = snapshot->frameRate, + .frameRateSelectionPriority = snapshot->frameRateSelectionPriority, + }; - auto it = mLegacyLayers.find(snapshot.sequence); - LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s", - snapshot.getDebugString().c_str()); + auto it = mLegacyLayers.find(snapshot->sequence); + LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s", + snapshot->getDebugString().c_str()); - if (snapshot.changes.test(Changes::Animation)) { - it->second->recordLayerHistoryAnimationTx(layerProps); - } + if (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) { + mScheduler->setDefaultFrameRateCompatibility(snapshot->sequence, + snapshot->defaultFrameRateCompatibility); + } - if (snapshot.clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) { - mScheduler->setDefaultFrameRateCompatibility(snapshot.sequence, - snapshot.defaultFrameRateCompatibility); - } + if (snapshot->changes.test(Changes::Animation)) { + it->second->recordLayerHistoryAnimationTx(layerProps, now); + } - if (snapshot.changes.test(Changes::FrameRate)) { - it->second->setFrameRateForLayerTree(snapshot.frameRate, layerProps); - } + if (snapshot->changes.test(Changes::FrameRate)) { + it->second->setFrameRateForLayerTree(snapshot->frameRate, layerProps, now); + } - if (snapshot.changes.test(Changes::Buffer)) { - it->second->recordLayerHistoryBufferUpdate(layerProps); + if (snapshot->changes.test(Changes::Buffer)) { + it->second->recordLayerHistoryBufferUpdate(layerProps, now); + } } } @@ -2379,8 +2381,8 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, mLayersIdsWithQueuedFrames.emplace(it->second->sequence); } + updateLayerHistory(latchTime); mLayerSnapshotBuilder.forEachVisibleSnapshot([&](const frontend::LayerSnapshot& snapshot) { - updateLayerHistory(snapshot); if (mLayersIdsWithQueuedFrames.find(snapshot.path.id) == mLayersIdsWithQueuedFrames.end()) return; @@ -4832,7 +4834,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin for (const auto& listener : listenerCallbacks) { mTransactionCallbackInvoker.addEmptyTransaction(listener); } - + nsecs_t now = systemTime(); uint32_t clientStateFlags = 0; for (auto& resolvedState : states) { if (mLegacyFrontEndEnabled) { @@ -4854,7 +4856,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin .setFrameRateVote = layer->getFrameRateForLayerTree(), .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(), }; - layer->recordLayerHistoryAnimationTx(layerProps); + layer->recordLayerHistoryAnimationTx(layerProps, now); } } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a5a2341b14..7b2d5908e6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -732,7 +732,7 @@ private: bool& out) REQUIRES(kMainThreadContext); bool updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, bool transactionsFlushed, bool& out) REQUIRES(kMainThreadContext); - void updateLayerHistory(const frontend::LayerSnapshot& snapshot); + void updateLayerHistory(nsecs_t now); frontend::Update flushLifecycleUpdates() REQUIRES(kMainThreadContext); void updateInputFlinger(VsyncId vsyncId, TimePoint frameTime); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index f4516c7635..858b882589 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -93,6 +93,7 @@ cc_test { "HWComposerTest.cpp", "OneShotTimerTest.cpp", "LayerHistoryTest.cpp", + "LayerHistoryIntegrationTest.cpp", "LayerInfoTest.cpp", "LayerMetadataTest.cpp", "LayerHierarchyTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h index d7ac038a84..27961faaf6 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h @@ -18,11 +18,13 @@ #include #include +#include #include "Client.h" // temporarily needed for LayerCreationArgs #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/LayerHierarchy.h" #include "FrontEnd/LayerLifecycleManager.h" +#include "FrontEnd/LayerSnapshotBuilder.h" namespace android::surfaceflinger::frontend { @@ -358,6 +360,19 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setDefaultFrameRateCompatibility(uint32_t id, int8_t defaultFrameRateCompatibility) { + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = + layer_state_t::eDefaultFrameRateCompatibilityChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.defaultFrameRateCompatibility = + defaultFrameRateCompatibility; + mLifecycleManager.applyTransactions(transactions); + } + void setRoundedCorners(uint32_t id, float radius) { std::vector transactions; transactions.emplace_back(); @@ -384,6 +399,16 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setBuffer(uint32_t id) { + static uint64_t sBufferId = 1; + setBuffer(id, + std::make_shared(1U /*width*/, 1U /*height*/, + sBufferId++, + HAL_PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_PROTECTED /*usage*/)); + } + void setBufferCrop(uint32_t id, const Rect& bufferCrop) { std::vector transactions; transactions.emplace_back(); @@ -409,4 +434,50 @@ protected: LayerLifecycleManager mLifecycleManager; }; +class LayerSnapshotTestBase : public LayerHierarchyTestBase { +protected: + LayerSnapshotTestBase() : LayerHierarchyTestBase() {} + + void createRootLayer(uint32_t id) override { + LayerHierarchyTestBase::createRootLayer(id); + setColor(id); + } + + void createLayer(uint32_t id, uint32_t parentId) override { + LayerHierarchyTestBase::createLayer(id, parentId); + setColor(parentId); + } + + void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) override { + LayerHierarchyTestBase::mirrorLayer(id, parent, layerToMirror); + setColor(id); + } + + void update(LayerSnapshotBuilder& snapshotBuilder) { + if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) { + mHierarchyBuilder.update(mLifecycleManager.getLayers(), + mLifecycleManager.getDestroyedLayers()); + } + LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(), + .layerLifecycleManager = mLifecycleManager, + .includeMetadata = false, + .displays = mFrontEndDisplayInfos, + .displayChanges = mHasDisplayChanges, + .globalShadowSettings = globalShadowSettings, + .supportsBlur = true, + .supportedLayerGenericMetadata = {}, + .genericLayerMetadataKeyMap = {}}; + snapshotBuilder.update(args); + + mLifecycleManager.commitChanges(); + } + + LayerHierarchyBuilder mHierarchyBuilder{{}}; + + DisplayInfos mFrontEndDisplayInfos; + bool mHasDisplayChanges = false; + + renderengine::ShadowSettings globalShadowSettings; +}; + } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp new file mode 100644 index 0000000000..a462082141 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp @@ -0,0 +1,873 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LayerHistoryIntegrationTest" + +#include +#include +#include +#include + +#include + +#include "FpsOps.h" +#include "LayerHierarchyTest.h" +#include "Scheduler/LayerHistory.h" +#include "Scheduler/LayerInfo.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockDisplayMode.h" +#include "mock/MockSchedulerCallback.h" + +namespace android::scheduler { + +using android::mock::createDisplayMode; + +class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase { +protected: + static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::HISTORY_SIZE; + static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfo::kMaxPeriodForFrequentLayerNs; + static constexpr auto FREQUENT_LAYER_WINDOW_SIZE = LayerInfo::kFrequentLayerWindowSize; + static constexpr auto PRESENT_TIME_HISTORY_DURATION = LayerInfo::HISTORY_DURATION; + + static constexpr Fps LO_FPS = 30_Hz; + static constexpr auto LO_FPS_PERIOD = LO_FPS.getPeriodNsecs(); + + static constexpr Fps HI_FPS = 90_Hz; + static constexpr auto HI_FPS_PERIOD = HI_FPS.getPeriodNsecs(); + + LayerHistoryIntegrationTest() : LayerSnapshotTestBase() { + mFlinger.resetScheduler(mScheduler); + mLifecycleManager = {}; + mHierarchyBuilder = {{}}; + } + + void updateLayerSnapshotsAndLayerHistory(nsecs_t now) { + LayerSnapshotTestBase::update(mFlinger.mutableLayerSnapshotBuilder()); + mFlinger.updateLayerHistory(now); + } + + void setBufferWithPresentTime(sp& layer, nsecs_t time) { + uint32_t sequence = static_cast(layer->sequence); + setBuffer(sequence); + layer->setDesiredPresentTime(time, false /*autotimestamp*/); + updateLayerSnapshotsAndLayerHistory(time); + } + + LayerHistory& history() { return mScheduler->mutableLayerHistory(); } + const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } + + LayerHistory::Summary summarizeLayerHistory(nsecs_t now) { + // LayerHistory::summarize makes no guarantee of the order of the elements in the summary + // however, for testing only, a stable order is required, therefore we sort the list here. + // Any tests requiring ordered results must create layers with names. + auto summary = history().summarize(*mScheduler->refreshRateSelector(), now); + std::sort(summary.begin(), summary.end(), + [](const RefreshRateSelector::LayerRequirement& lhs, + const RefreshRateSelector::LayerRequirement& rhs) -> bool { + return lhs.name < rhs.name; + }); + return summary; + } + + size_t layerCount() const { return mScheduler->layerHistorySize(); } + size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { + return history().mActiveLayerInfos.size(); + } + + auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mActiveLayerInfos; + return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) { + return pair.second.second->isFrequent(now).isFrequent; + }); + } + + auto animatingLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mActiveLayerInfos; + return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) { + return pair.second.second->isAnimating(now); + }); + } + + auto clearLayerHistoryCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mActiveLayerInfos; + return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) { + return pair.second.second->isFrequent(now).clearHistory; + }); + } + + void setDefaultLayerVote(Layer* layer, + LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS { + auto [found, layerPair] = history().findLayer(layer->getSequence()); + if (found != LayerHistory::LayerStatus::NotFound) { + layerPair->second->setDefaultLayerVote(vote); + } + } + + auto createLegacyAndFrontedEndLayer(uint32_t sequence) { + std::string layerName = "test layer:" + std::to_string(sequence); + const auto layer = + sp::make(LayerCreationArgs{mFlinger.flinger(), + nullptr, + layerName, + 0, + {}, + std::make_optional(sequence)}); + mFlinger.injectLegacyLayer(layer); + createRootLayer(sequence); + return layer; + } + + auto destroyLayer(sp& layer) { + uint32_t sequence = static_cast(layer->sequence); + mFlinger.releaseLegacyLayer(sequence); + layer.clear(); + destroyLayerHandle(sequence); + } + + void recordFramesAndExpect(sp& layer, nsecs_t& time, Fps frameRate, + Fps desiredRefreshRate, int numFrames) { + LayerHistory::Summary summary; + for (int i = 0; i < numFrames; i++) { + setBufferWithPresentTime(layer, time); + time += frameRate.getPeriodNsecs(); + + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + ASSERT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate); + } + + std::shared_ptr mSelector = + std::make_shared(makeModes(createDisplayMode(DisplayModeId(0), + LO_FPS), + createDisplayMode(DisplayModeId(1), + HI_FPS)), + DisplayModeId(0)); + + mock::SchedulerCallback mSchedulerCallback; + + TestableScheduler* mScheduler = new TestableScheduler(mSelector, mSchedulerCallback); + + TestableSurfaceFlinger mFlinger; +}; + +namespace { + +TEST_F(LayerHistoryIntegrationTest, singleLayerNoVoteDefaultCompatibility) { + createLegacyAndFrontedEndLayer(1); + nsecs_t time = systemTime(); + + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + // No layers returned if no layers are active. + EXPECT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); + + setBuffer(1); + setDefaultFrameRateCompatibility(1, ANATIVEWINDOW_FRAME_RATE_NO_VOTE); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(1u, activeLayerCount()); +} + +TEST_F(LayerHistoryIntegrationTest, singleLayerMinVoteDefaultCompatibility) { + createLegacyAndFrontedEndLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + EXPECT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); + + setBuffer(1); + setDefaultFrameRateCompatibility(1, ANATIVEWINDOW_FRAME_RATE_MIN); + updateLayerSnapshotsAndLayerHistory(time); + + auto summary = summarizeLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); +} + +TEST_F(LayerHistoryIntegrationTest, oneInvisibleLayer) { + createLegacyAndFrontedEndLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + setBuffer(1); + updateLayerSnapshotsAndLayerHistory(time); + auto summary = summarizeLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + // Layer is still considered inactive so we expect to get Min + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + + hideLayer(1); + setBuffer(1); + updateLayerSnapshotsAndLayerHistory(time); + + summary = summarizeLayerHistory(time); + EXPECT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVote) { + createLegacyAndFrontedEndLayer(1); + setFrameRate(1, 73.4f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitExactVote) { + createLegacyAndFrontedEndLayer(1); + setFrameRate(1, 73.4f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitCategory) { + createLegacyAndFrontedEndLayer(1); + setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + // First LayerRequirement is the frame rate specification + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); +} + +TEST_F(LayerHistoryIntegrationTest, multipleLayers) { + auto layer1 = createLegacyAndFrontedEndLayer(1); + auto layer2 = createLegacyAndFrontedEndLayer(2); + auto layer3 = createLegacyAndFrontedEndLayer(3); + + nsecs_t time = systemTime(); + + EXPECT_EQ(3u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + LayerHistory::Summary summary; + + // layer1 is active but infrequent. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer1, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer2 is frequent and has high refresh rate. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer2, time); + time += HI_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + // layer1 is still active but infrequent. + setBufferWithPresentTime(layer1, time); + + ASSERT_EQ(2u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote); + ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); + EXPECT_EQ(HI_FPS, summarizeLayerHistory(time)[1].desiredRefreshRate); + + EXPECT_EQ(2u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer1 is no longer active. + // layer2 is frequent and has low refresh rate. + for (size_t i = 0; i < 2 * PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer2, time); + time += LO_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 has high refresh rate but not enough history. + constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + if (i % RATIO == 0) { + setBufferWithPresentTime(layer2, time); + } + + setBufferWithPresentTime(layer3, time); + time += HI_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(2u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summary[1].vote); + EXPECT_EQ(2u, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer3 becomes recently active. + setBufferWithPresentTime(layer3, time); + summary = summarizeLayerHistory(time); + ASSERT_EQ(2u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); + EXPECT_EQ(HI_FPS, summary[1].desiredRefreshRate); + EXPECT_EQ(2u, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer1 expires. + destroyLayer(layer1); + updateLayerSnapshotsAndLayerHistory(time); + + summary = summarizeLayerHistory(time); + ASSERT_EQ(2u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); + EXPECT_EQ(HI_FPS, summary[1].desiredRefreshRate); + EXPECT_EQ(2u, layerCount()); + EXPECT_EQ(2u, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 becomes inactive. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer2, time); + time += LO_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 expires. + destroyLayer(layer2); + updateLayerSnapshotsAndLayerHistory(time); + summary = summarizeLayerHistory(time); + EXPECT_TRUE(summary.empty()); + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer3 becomes active and has high refresh rate. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) { + setBufferWithPresentTime(layer3, time); + time += HI_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_EQ(HI_FPS, summary[0].desiredRefreshRate); + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer3 expires. + destroyLayer(layer3); + updateLayerSnapshotsAndLayerHistory(time); + summary = summarizeLayerHistory(time); + EXPECT_TRUE(summary.empty()); + EXPECT_EQ(0u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, inactiveLayers) { + auto layer = createLegacyAndFrontedEndLayer(1); + nsecs_t time = systemTime(); + + // the very first updates makes the layer frequent + for (size_t i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { + setBufferWithPresentTime(layer, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + + EXPECT_EQ(1u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + } + + // the next update with the MAX_FREQUENT_LAYER_PERIOD_NS will get us to infrequent + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + setBufferWithPresentTime(layer, time); + + EXPECT_EQ(1u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // advance the time for the previous frame to be inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + + // Now even if we post a quick few frame we should stay infrequent + for (size_t i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + + EXPECT_EQ(1u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + } + + // More quick frames will get us to frequent again + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + + EXPECT_EQ(1u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) { + auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); + auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); + hideLayer(2); + setFrameRate(1, 60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRate(2, 90.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + nsecs_t time = systemTime(); + + // Post a buffer to the layers to make them active + setBufferWithPresentTime(explicitVisiblelayer, time); + setBufferWithPresentTime(explicitInvisiblelayer, time); + + EXPECT_EQ(2u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(2u, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, infrequentAnimatingLayer) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // layer is active but infrequent. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // another update with the same cadence keep in infrequent + setBufferWithPresentTime(layer, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + mFlinger.mutableLayerSnapshotBuilder().getSnapshot(1)->changes |= + frontend::RequestedLayerState::Changes::Animation; + mFlinger.updateLayerHistory(time); + // an update as animation will immediately vote for Max + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(1, animatingLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, frequentLayerBecomingInfrequentAndBack) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // Fill up the window with frequent updates + for (size_t i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += (60_Hz).getPeriodNsecs(); + + EXPECT_EQ(1u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + } + + // posting a buffer after long inactivity should retain the layer as active + time += std::chrono::nanoseconds(3s).count(); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(0, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // posting more infrequent buffer should make the layer infrequent + time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count(); + setBufferWithPresentTime(layer, time); + time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count(); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(0, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // posting another buffer should keep the layer infrequent + setBufferWithPresentTime(layer, time); + EXPECT_EQ(0, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // posting more buffers would mean starting of an animation, so making the layer frequent + setBufferWithPresentTime(layer, time); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(1, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // posting a buffer after long inactivity should retain the layer as active + time += std::chrono::nanoseconds(3s).count(); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(0, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // posting another buffer should keep the layer frequent + time += (60_Hz).getPeriodNsecs(); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(0, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, inconclusiveLayerBecomingFrequent) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // Fill up the window with frequent updates + for (size_t i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += (60_Hz).getPeriodNsecs(); + + EXPECT_EQ(1u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + } + + // posting infrequent buffers after long inactivity should make the layer + // inconclusive but frequent. + time += std::chrono::nanoseconds(3s).count(); + setBufferWithPresentTime(layer, time); + time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count(); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(0, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // posting more buffers should make the layer frequent and switch the refresh rate to max + // by clearing the history + setBufferWithPresentTime(layer, time); + setBufferWithPresentTime(layer, time); + setBufferWithPresentTime(layer, time); + EXPECT_EQ(1, clearLayerHistoryCount(time)); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, getFramerate) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // layer is active but infrequent. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + } + + float expectedFramerate = 1e9f / MAX_FREQUENT_LAYER_PERIOD_NS.count(); + EXPECT_FLOAT_EQ(expectedFramerate, history().getLayerFramerate(time, layer->getSequence())); +} + +TEST_F(LayerHistoryIntegrationTest, heuristicLayer60Hz) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + for (float fps = 54.0f; fps < 65.0f; fps += 0.1f) { + recordFramesAndExpect(layer, time, Fps::fromValue(fps), 60_Hz, PRESENT_TIME_HISTORY_SIZE); + } +} + +TEST_F(LayerHistoryIntegrationTest, heuristicLayer60_30Hz) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + recordFramesAndExpect(layer, time, 60_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); + + recordFramesAndExpect(layer, time, 60_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 30_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 30_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 60_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 60_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); +} + +TEST_F(LayerHistoryIntegrationTest, heuristicLayerNotOscillating) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 26.9_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 26_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 26.9_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); +} + +TEST_F(LayerHistoryIntegrationTest, smallDirtyLayer) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + LayerHistory::Summary summary; + + // layer is active but infrequent. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + auto props = layer->getLayerProps(); + if (i % 3 == 0) { + props.isSmallDirty = false; + } else { + props.isSmallDirty = true; + } + + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); + EXPECT_GE(HI_FPS, summary[0].desiredRefreshRate); +} + +TEST_F(LayerHistoryIntegrationTest, DISABLED_smallDirtyInMultiLayer) { + auto uiLayer = createLegacyAndFrontedEndLayer(1); + auto videoLayer = createLegacyAndFrontedEndLayer(2); + setFrameRate(2, 30.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + + nsecs_t time = systemTime(); + + EXPECT_EQ(2u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + LayerHistory::Summary summary; + + // uiLayer is updating small dirty. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) { + auto props = uiLayer->getLayerProps(); + props.isSmallDirty = true; + setBuffer(1); + uiLayer->setDesiredPresentTime(0, false /*autotimestamp*/); + updateLayerSnapshotsAndLayerHistory(time); + setBufferWithPresentTime(videoLayer, time); + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); + ASSERT_EQ(30_Hz, summary[0].desiredRefreshRate); +} + +class LayerHistoryIntegrationTestParameterized + : public LayerHistoryIntegrationTest, + public testing::WithParamInterface {}; + +TEST_P(LayerHistoryIntegrationTestParameterized, HeuristicLayerWithInfrequentLayer) { + std::chrono::nanoseconds infrequentUpdateDelta = GetParam(); + auto heuristicLayer = createLegacyAndFrontedEndLayer(1); + auto infrequentLayer = createLegacyAndFrontedEndLayer(2); + + const nsecs_t startTime = systemTime(); + + const std::chrono::nanoseconds heuristicUpdateDelta = 41'666'667ns; + setBufferWithPresentTime(heuristicLayer, startTime); + setBufferWithPresentTime(infrequentLayer, startTime); + + nsecs_t time = startTime; + nsecs_t lastInfrequentUpdate = startTime; + const size_t totalInfrequentLayerUpdates = FREQUENT_LAYER_WINDOW_SIZE * 5; + size_t infrequentLayerUpdates = 0; + while (infrequentLayerUpdates <= totalInfrequentLayerUpdates) { + time += heuristicUpdateDelta.count(); + setBufferWithPresentTime(heuristicLayer, time); + + if (time - lastInfrequentUpdate >= infrequentUpdateDelta.count()) { + ALOGI("submitting infrequent frame [%zu/%zu]", infrequentLayerUpdates, + totalInfrequentLayerUpdates); + lastInfrequentUpdate = time; + setBufferWithPresentTime(infrequentLayer, time); + infrequentLayerUpdates++; + } + + if (time - startTime > PRESENT_TIME_HISTORY_DURATION.count()) { + ASSERT_NE(0u, summarizeLayerHistory(time).size()); + ASSERT_GE(2u, summarizeLayerHistory(time).size()); + + bool max = false; + bool min = false; + Fps heuristic; + for (const auto& layer : summarizeLayerHistory(time)) { + if (layer.vote == LayerHistory::LayerVoteType::Heuristic) { + heuristic = layer.desiredRefreshRate; + } else if (layer.vote == LayerHistory::LayerVoteType::Max) { + max = true; + } else if (layer.vote == LayerHistory::LayerVoteType::Min) { + min = true; + } + } + + if (infrequentLayerUpdates > FREQUENT_LAYER_WINDOW_SIZE) { + EXPECT_EQ(24_Hz, heuristic); + EXPECT_FALSE(max); + if (summarizeLayerHistory(time).size() == 2) { + EXPECT_TRUE(min); + } + } + } + } +} + +INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryIntegrationTestParameterized, + ::testing::Values(1s, 2s, 3s, 4s, 5s)); + +} // namespace +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 549a362af3..33c1d86847 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -45,6 +45,8 @@ using MockLayer = android::mock::MockLayer; using android::mock::createDisplayMode; +// WARNING: LEGACY TESTS FOR LEGACY FRONT END +// Update LayerHistoryIntegrationTest instead class LayerHistoryTest : public testing::Test { protected: static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::HISTORY_SIZE; diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 69316bf4e5..e8568162b8 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -50,27 +50,12 @@ using namespace ftl::flag_operators; --gtest_filter="LayerSnapshotTest.*" --gtest_brief=1 */ -class LayerSnapshotTest : public LayerHierarchyTestBase { +class LayerSnapshotTest : public LayerSnapshotTestBase { protected: - LayerSnapshotTest() : LayerHierarchyTestBase() { + LayerSnapshotTest() : LayerSnapshotTestBase() { UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); } - void createRootLayer(uint32_t id) override { - LayerHierarchyTestBase::createRootLayer(id); - setColor(id); - } - - void createLayer(uint32_t id, uint32_t parentId) override { - LayerHierarchyTestBase::createLayer(id, parentId); - setColor(parentId); - } - - void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) override { - LayerHierarchyTestBase::mirrorLayer(id, parent, layerToMirror); - setColor(id); - } - void update(LayerSnapshotBuilder& actualBuilder, LayerSnapshotBuilder::Args& args) { if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) { mHierarchyBuilder.update(mLifecycleManager.getLayers(), @@ -111,11 +96,7 @@ protected: LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath path) { return mSnapshotBuilder.getSnapshot(path); } - - LayerHierarchyBuilder mHierarchyBuilder{{}}; LayerSnapshotBuilder mSnapshotBuilder; - DisplayInfos mFrontEndDisplayInfos; - renderengine::ShadowSettings globalShadowSettings; static const std::vector STARTING_ZORDER; }; const std::vector LayerSnapshotTest::STARTING_ZORDER = {1, 11, 111, 12, 121, diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 173f9417b9..a6f23ed091 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -192,7 +192,7 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSup // recordLayerHistory should be a noop ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); - mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, + mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0, LayerHistory::LayerUpdateType::Buffer); ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); @@ -218,7 +218,7 @@ TEST_F(SchedulerTest, updateDisplayModes) { kDisplay1Mode60->getId())); ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); - mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, + mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0, LayerHistory::LayerUpdateType::Buffer); ASSERT_EQ(1u, mScheduler->getNumActiveLayers()); } @@ -273,7 +273,7 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { const sp layer = sp::make(mFlinger.flinger()); EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true)); - mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, + mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, systemTime(), LayerHistory::LayerUpdateType::Buffer); constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON; diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index dd998ba629..b54392e651 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -604,6 +604,13 @@ public: return static_cast(mFlinger->mFrameTracer.get()); } + void injectLegacyLayer(sp layer) { + mFlinger->mLegacyLayers[static_cast(layer->sequence)] = layer; + }; + + void releaseLegacyLayer(uint32_t sequence) { mFlinger->mLegacyLayers.erase(sequence); }; + + auto updateLayerHistory(nsecs_t now) { return mFlinger->updateLayerHistory(now); }; /* ------------------------------------------------------------------------ * Read-write access to private data to set up preconditions and assert * post-conditions. @@ -644,8 +651,8 @@ public: } auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; } - auto& mutableLayersPendingRemoval() { return mFlinger->mLayersPendingRemoval; } + auto& mutableLayerSnapshotBuilder() { return mFlinger->mLayerSnapshotBuilder; }; auto fromHandle(const sp& handle) { return LayerHandle::getLayer(handle); } -- cgit v1.2.3-59-g8ed1b From d9e4f46cc957205d9a583f0dbccbcefeb66cf9bf Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 6 Oct 2023 04:05:45 +0000 Subject: Clean up duplicate shadow lengths in layer snapshot The shadow length is currently tracked in both the LayerFE CompositionState and the shadow settings, which are used by the RenderEngine. We can consolidate these fields and track shadow settings in the LayerFE CompositionState. This makes sense because we want the LayerFE CompositionState to contain all relevant information that it can pass to the RenderEngine without calling back into the frontend. Bug: 302551905 Test: presubmit Change-Id: I583c43993cf73784c6fec9ec2d40f2c76d21adeb --- .../include/renderengine/LayerSettings.h | 42 +------------- libs/renderengine/tests/RenderEngineTest.cpp | 55 ++++++++---------- libs/ui/include/ui/ShadowSettings.h | 65 ++++++++++++++++++++++ .../compositionengine/LayerFECompositionState.h | 4 +- .../src/LayerFECompositionState.cpp | 2 +- .../CompositionEngine/src/Output.cpp | 4 +- .../CompositionEngine/src/OutputLayer.cpp | 4 +- .../CompositionEngine/tests/OutputLayerTest.cpp | 4 +- .../CompositionEngine/tests/OutputTest.cpp | 6 +- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 1 - services/surfaceflinger/FrontEnd/LayerSnapshot.h | 1 - .../FrontEnd/LayerSnapshotBuilder.cpp | 12 ++-- .../surfaceflinger/FrontEnd/LayerSnapshotBuilder.h | 4 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/LayerFE.cpp | 2 +- services/surfaceflinger/LayerProtoHelper.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../Tracing/tools/LayerTraceGenerator.cpp | 2 +- .../tests/unittests/LayerHierarchyTest.h | 3 +- .../tests/unittests/LayerSnapshotTest.cpp | 1 - 20 files changed, 117 insertions(+), 101 deletions(-) create mode 100644 libs/ui/include/ui/ShadowSettings.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 28aa4dd71d..8ac0af47c6 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -97,36 +98,6 @@ struct PixelSource { half3 solidColor = half3(0.0f, 0.0f, 0.0f); }; -/* - * Contains the configuration for the shadows drawn by single layer. Shadow follows - * material design guidelines. - */ -struct ShadowSettings { - // Boundaries of the shadow. - FloatRect boundaries = FloatRect(); - - // Color to the ambient shadow. The alpha is premultiplied. - vec4 ambientColor = vec4(); - - // Color to the spot shadow. The alpha is premultiplied. The position of the spot shadow - // depends on the light position. - vec4 spotColor = vec4(); - - // Position of the light source used to cast the spot shadow. - vec3 lightPos = vec3(); - - // Radius of the spot light source. Smaller radius will have sharper edges, - // larger radius will have softer shadows - float lightRadius = 0.f; - - // Length of the cast shadow. If length is <= 0.f no shadows will be drawn. - float length = 0.f; - - // If true fill in the casting layer is translucent and the shadow needs to fill the bounds. - // Otherwise the shadow will only be drawn around the edges of the casting layer. - bool casterIsTranslucent = false; -}; - // The settings that RenderEngine requires for correctly rendering a Layer. struct LayerSettings { // Geometry information @@ -194,17 +165,6 @@ static inline bool operator==(const PixelSource& lhs, const PixelSource& rhs) { return lhs.buffer == rhs.buffer && lhs.solidColor == rhs.solidColor; } -static inline bool operator==(const ShadowSettings& lhs, const ShadowSettings& rhs) { - return lhs.boundaries == rhs.boundaries && lhs.ambientColor == rhs.ambientColor && - lhs.spotColor == rhs.spotColor && lhs.lightPos == rhs.lightPos && - lhs.lightRadius == rhs.lightRadius && lhs.length == rhs.length && - lhs.casterIsTranslucent == rhs.casterIsTranslucent; -} - -static inline bool operator!=(const ShadowSettings& lhs, const ShadowSettings& rhs) { - return !(operator==(lhs, rhs)); -} - static inline bool operator==(const LayerSettings& lhs, const LayerSettings& rhs) { if (lhs.blurRegions.size() != rhs.blurRegions.size()) { return false; diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 7dde71632b..6023808aaf 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -403,7 +403,7 @@ public: } void expectShadowColor(const renderengine::LayerSettings& castingLayer, - const renderengine::ShadowSettings& shadow, const ubyte4& casterColor, + const ShadowSettings& shadow, const ubyte4& casterColor, const ubyte4& backgroundColor) { const Rect casterRect(castingLayer.geometry.boundaries); Region casterRegion = Region(casterRect); @@ -443,8 +443,7 @@ public: backgroundColor.a); } - void expectShadowColorWithoutCaster(const FloatRect& casterBounds, - const renderengine::ShadowSettings& shadow, + void expectShadowColorWithoutCaster(const FloatRect& casterBounds, const ShadowSettings& shadow, const ubyte4& backgroundColor) { const float shadowInset = shadow.length * -1.0f; const Rect casterRect(casterBounds); @@ -463,9 +462,9 @@ public: backgroundColor.a); } - static renderengine::ShadowSettings getShadowSettings(const vec2& casterPos, float shadowLength, - bool casterIsTranslucent) { - renderengine::ShadowSettings shadow; + static ShadowSettings getShadowSettings(const vec2& casterPos, float shadowLength, + bool casterIsTranslucent) { + ShadowSettings shadow; shadow.ambientColor = {0.0f, 0.0f, 0.0f, 0.039f}; shadow.spotColor = {0.0f, 0.0f, 0.0f, 0.19f}; shadow.lightPos = vec3(casterPos.x, casterPos.y, 0); @@ -602,12 +601,10 @@ public: void fillGreenColorBufferThenClearRegion(); template - void drawShadow(const renderengine::LayerSettings& castingLayer, - const renderengine::ShadowSettings& shadow, const ubyte4& casterColor, - const ubyte4& backgroundColor); + void drawShadow(const renderengine::LayerSettings& castingLayer, const ShadowSettings& shadow, + const ubyte4& casterColor, const ubyte4& backgroundColor); - void drawShadowWithoutCaster(const FloatRect& castingBounds, - const renderengine::ShadowSettings& shadow, + void drawShadowWithoutCaster(const FloatRect& castingBounds, const ShadowSettings& shadow, const ubyte4& backgroundColor); // Tonemaps grey values from sourceDataspace -> Display P3 and checks that GPU and CPU @@ -1337,8 +1334,8 @@ void RenderEngineTest::fillBufferWithoutPremultiplyAlpha() { template void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLayer, - const renderengine::ShadowSettings& shadow, - const ubyte4& casterColor, const ubyte4& backgroundColor) { + const ShadowSettings& shadow, const ubyte4& casterColor, + const ubyte4& backgroundColor) { renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; settings.physicalDisplay = fullscreenRect(); @@ -1374,7 +1371,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye } void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, - const renderengine::ShadowSettings& shadow, + const ShadowSettings& shadow, const ubyte4& backgroundColor) { renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -2103,9 +2100,8 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) { const float shadowLength = 5.0f; Rect casterBounds(DEFAULT_DISPLAY_WIDTH / 3.0f, DEFAULT_DISPLAY_HEIGHT / 3.0f); casterBounds.offsetBy(shadowLength + 1, shadowLength + 1); - renderengine::ShadowSettings settings = - getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength, - false /* casterIsTranslucent */); + ShadowSettings settings = getShadowSettings(vec2(casterBounds.left, casterBounds.top), + shadowLength, false /* casterIsTranslucent */); drawShadowWithoutCaster(casterBounds.toFloatRect(), settings, backgroundColor); expectShadowColorWithoutCaster(casterBounds.toFloatRect(), settings, backgroundColor); @@ -2127,9 +2123,8 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_casterLayerMinSize) { renderengine::LayerSettings castingLayer; castingLayer.geometry.boundaries = casterBounds.toFloatRect(); castingLayer.alpha = 1.0f; - renderengine::ShadowSettings settings = - getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength, - false /* casterIsTranslucent */); + ShadowSettings settings = getShadowSettings(vec2(casterBounds.left, casterBounds.top), + shadowLength, false /* casterIsTranslucent */); drawShadow(castingLayer, settings, casterColor, backgroundColor); expectShadowColor(castingLayer, settings, casterColor, backgroundColor); @@ -2152,9 +2147,8 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_casterColorLayer) { castingLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; castingLayer.geometry.boundaries = casterBounds.toFloatRect(); castingLayer.alpha = 1.0f; - renderengine::ShadowSettings settings = - getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength, - false /* casterIsTranslucent */); + ShadowSettings settings = getShadowSettings(vec2(casterBounds.left, casterBounds.top), + shadowLength, false /* casterIsTranslucent */); drawShadow(castingLayer, settings, casterColor, backgroundColor); expectShadowColor(castingLayer, settings, casterColor, backgroundColor); @@ -2177,9 +2171,8 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_casterOpaqueBufferLayer) { castingLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; castingLayer.geometry.boundaries = casterBounds.toFloatRect(); castingLayer.alpha = 1.0f; - renderengine::ShadowSettings settings = - getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength, - false /* casterIsTranslucent */); + ShadowSettings settings = getShadowSettings(vec2(casterBounds.left, casterBounds.top), + shadowLength, false /* casterIsTranslucent */); drawShadow>(castingLayer, settings, casterColor, backgroundColor); @@ -2204,9 +2197,8 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_casterWithRoundedCorner) { castingLayer.geometry.roundedCornersRadius = {3.0f, 3.0f}; castingLayer.geometry.roundedCornersCrop = casterBounds.toFloatRect(); castingLayer.alpha = 1.0f; - renderengine::ShadowSettings settings = - getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength, - false /* casterIsTranslucent */); + ShadowSettings settings = getShadowSettings(vec2(casterBounds.left, casterBounds.top), + shadowLength, false /* casterIsTranslucent */); drawShadow>(castingLayer, settings, casterColor, backgroundColor); @@ -2227,9 +2219,8 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) { renderengine::LayerSettings castingLayer; castingLayer.geometry.boundaries = casterBounds.toFloatRect(); castingLayer.alpha = 0.5f; - renderengine::ShadowSettings settings = - getShadowSettings(vec2(casterBounds.left, casterBounds.top), shadowLength, - true /* casterIsTranslucent */); + ShadowSettings settings = getShadowSettings(vec2(casterBounds.left, casterBounds.top), + shadowLength, true /* casterIsTranslucent */); drawShadow>(castingLayer, settings, casterColor, backgroundColor); diff --git a/libs/ui/include/ui/ShadowSettings.h b/libs/ui/include/ui/ShadowSettings.h new file mode 100644 index 0000000000..c0b83b8691 --- /dev/null +++ b/libs/ui/include/ui/ShadowSettings.h @@ -0,0 +1,65 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "FloatRect.h" + +namespace android { + +/* + * Contains the configuration for the shadows drawn by single layer. Shadow follows + * material design guidelines. + */ +struct ShadowSettings { + // Boundaries of the shadow. + FloatRect boundaries = FloatRect(); + + // Color to the ambient shadow. The alpha is premultiplied. + vec4 ambientColor = vec4(); + + // Color to the spot shadow. The alpha is premultiplied. The position of the spot shadow + // depends on the light position. + vec4 spotColor = vec4(); + + // Position of the light source used to cast the spot shadow. + vec3 lightPos = vec3(); + + // Radius of the spot light source. Smaller radius will have sharper edges, + // larger radius will have softer shadows + float lightRadius = 0.f; + + // Length of the cast shadow. If length is <= 0.f no shadows will be drawn. + float length = 0.f; + + // If true fill in the casting layer is translucent and the shadow needs to fill the bounds. + // Otherwise the shadow will only be drawn around the edges of the casting layer. + bool casterIsTranslucent = false; +}; + +static inline bool operator==(const ShadowSettings& lhs, const ShadowSettings& rhs) { + return lhs.boundaries == rhs.boundaries && lhs.ambientColor == rhs.ambientColor && + lhs.spotColor == rhs.spotColor && lhs.lightPos == rhs.lightPos && + lhs.lightRadius == rhs.lightRadius && lhs.length == rhs.length && + lhs.casterIsTranslucent == rhs.casterIsTranslucent; +} + +static inline bool operator!=(const ShadowSettings& lhs, const ShadowSettings& rhs) { + return !(operator==(lhs, rhs)); +} + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 35ca3a58d9..11759b855f 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -26,6 +26,7 @@ #include #include #include +#include #include // TODO(b/129481165): remove the #pragma below and fix conversion issues @@ -132,8 +133,7 @@ struct LayerFECompositionState { // The bounds of the layer in layer local coordinates FloatRect geomLayerBounds; - // length of the shadow in screen space - float shadowRadius{0.f}; + ShadowSettings shadowSettings; // List of regions that require blur std::vector blurRegions; diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index 426cc57db8..2d10866db3 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -68,7 +68,7 @@ void LayerFECompositionState::dump(std::string& out) const { dumpVal(out, "geomLayerBounds", geomLayerBounds); out.append(" "); - dumpVal(out, "shadowRadius", shadowRadius); + dumpVal(out, "shadowLength", shadowSettings.length); out.append("\n "); dumpVal(out, "blend", toString(blendMode), blendMode); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 775e6d5094..fa3733b540 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -588,10 +588,10 @@ void Output::ensureOutputLayerIfVisible(sp& layerFE, const Rect visibleRect(tr.transform(layerFEState->geomLayerBounds)); visibleRegion.set(visibleRect); - if (layerFEState->shadowRadius > 0.0f) { + if (layerFEState->shadowSettings.length > 0.0f) { // if the layer casts a shadow, offset the layers visible region and // calculate the shadow region. - const auto inset = static_cast(ceilf(layerFEState->shadowRadius) * -1.0f); + const auto inset = static_cast(ceilf(layerFEState->shadowSettings.length) * -1.0f); Rect visibleRectWithShadows(visibleRect); visibleRectWithShadows.inset(inset, inset, inset, inset); visibleRegion.set(visibleRectWithShadows); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index fe56969884..7fe3369f88 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -222,8 +222,8 @@ Rect OutputLayer::calculateOutputDisplayFrame() const { // Some HWCs may clip client composited input to its displayFrame. Make sure // that this does not cut off the shadow. - if (layerState.forceClientComposition && layerState.shadowRadius > 0.0f) { - const auto outset = layerState.shadowRadius; + if (layerState.forceClientComposition && layerState.shadowSettings.length > 0.0f) { + const auto outset = layerState.shadowSettings.length; geomLayerBounds.left -= outset; geomLayerBounds.top -= outset; geomLayerBounds.right += outset; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 630906a5b7..1c54469cc0 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -334,7 +334,7 @@ TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) { TEST_F(OutputLayerDisplayFrameTest, shadowExpandsDisplayFrame) { const int kShadowRadius = 5; - mLayerFEState.shadowRadius = kShadowRadius; + mLayerFEState.shadowSettings.length = kShadowRadius; mLayerFEState.forceClientComposition = true; mLayerFEState.geomLayerBounds = FloatRect{100.f, 100.f, 200.f, 200.f}; @@ -345,7 +345,7 @@ TEST_F(OutputLayerDisplayFrameTest, shadowExpandsDisplayFrame) { TEST_F(OutputLayerDisplayFrameTest, shadowExpandsDisplayFrame_onlyIfForcingClientComposition) { const int kShadowRadius = 5; - mLayerFEState.shadowRadius = kShadowRadius; + mLayerFEState.shadowSettings.length = kShadowRadius; mLayerFEState.forceClientComposition = false; mLayerFEState.geomLayerBounds = FloatRect{100.f, 100.f, 200.f, 200.f}; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index ee6998aef8..cdcb68d9fc 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -1830,7 +1830,7 @@ TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesWithShadowsTest) ui::Transform translate; translate.set(50, 50); mLayer.layerFEState.geomLayerTransform = translate; - mLayer.layerFEState.shadowRadius = 10.0f; + mLayer.layerFEState.shadowSettings.length = 10.0f; mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500)); // half of the layer including the casting shadow is covered and opaque @@ -1872,7 +1872,7 @@ TEST_F(OutputEnsureOutputLayerIfVisibleTest, shadowRegionOnlyTest) { ui::Transform translate; translate.set(50, 50); mLayer.layerFEState.geomLayerTransform = translate; - mLayer.layerFEState.shadowRadius = 10.0f; + mLayer.layerFEState.shadowSettings.length = 10.0f; mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500)); // Casting layer is covered by an opaque region leaving only part of its shadow to be drawn @@ -1897,7 +1897,7 @@ TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifLayerWithShadow ui::Transform translate; translate.set(50, 50); mLayer.layerFEState.geomLayerTransform = translate; - mLayer.layerFEState.shadowRadius = 10.0f; + mLayer.layerFEState.shadowSettings.length = 10.0f; mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500)); // Casting layer and its shadows are covered by an opaque region diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index f9c8e812dd..7a85da056e 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -382,7 +382,6 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate sidebandStream = requested.sidebandStream; } if (forceUpdate || requested.what & layer_state_t::eShadowRadiusChanged) { - shadowRadius = requested.shadowRadius; shadowSettings.length = requested.shadowRadius; } if (forceUpdate || requested.what & layer_state_t::eFrameRateSelectionPriority) { diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index a1c72a94e0..80a51ea94c 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -69,7 +69,6 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { RoundedCornerState roundedCorner; FloatRect transformedBounds; Rect transformedBoundsWithoutTransparentRegion; - renderengine::ShadowSettings shadowSettings; bool premultipliedAlpha; ui::Transform parentTransform; Rect bufferSize; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index a1796e1eb0..03c09932d3 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -353,7 +353,7 @@ LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() { snapshot.isSecure = false; snapshot.color.a = 1.0_hf; snapshot.colorTransformIsIdentity = true; - snapshot.shadowRadius = 0.f; + snapshot.shadowSettings.length = 0.f; snapshot.layerMetadata.mMap.clear(); snapshot.relativeLayerMetadata.mMap.clear(); snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED; @@ -990,9 +990,12 @@ void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, } void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&, - const renderengine::ShadowSettings& globalShadowSettings) { - if (snapshot.shadowRadius > 0.f) { - snapshot.shadowSettings = globalShadowSettings; + const ShadowSettings& globalShadowSettings) { + if (snapshot.shadowSettings.length > 0.f) { + snapshot.shadowSettings.ambientColor = globalShadowSettings.ambientColor; + snapshot.shadowSettings.spotColor = globalShadowSettings.spotColor; + snapshot.shadowSettings.lightPos = globalShadowSettings.lightPos; + snapshot.shadowSettings.lightRadius = globalShadowSettings.lightRadius; // Note: this preserves existing behavior of shadowing the entire layer and not cropping // it if transparent regions are present. This may not be necessary since shadows are @@ -1006,7 +1009,6 @@ void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const Requeste snapshot.shadowSettings.ambientColor *= snapshot.alpha; snapshot.shadowSettings.spotColor *= snapshot.alpha; } - snapshot.shadowSettings.length = snapshot.shadowRadius; } void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h index 3d64b362ea..1506913e15 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h @@ -47,7 +47,7 @@ public: const DisplayInfos& displays; // Set to true if there were display changes since last update. bool displayChanges = false; - const renderengine::ShadowSettings& globalShadowSettings; + const ShadowSettings& globalShadowSettings; bool supportsBlur = true; bool forceFullDamage = false; std::optional parentCrop = std::nullopt; @@ -108,7 +108,7 @@ private: void updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& layerState, const LayerSnapshot& parentSnapshot, uint32_t displayRotationFlags); static void updateShadows(LayerSnapshot& snapshot, const RequestedLayerState& requested, - const renderengine::ShadowSettings& globalShadowSettings); + const ShadowSettings& globalShadowSettings); void updateInput(LayerSnapshot& snapshot, const RequestedLayerState& requested, const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath& path, const Args& args); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 33d1eeb7cc..2dc8758c3d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -572,7 +572,7 @@ void Layer::prepareBasicGeometryCompositionState() { snapshot->outputFilter = getOutputFilter(); snapshot->isVisible = isVisible(); snapshot->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f; - snapshot->shadowRadius = mEffectiveShadowRadius; + snapshot->shadowSettings.length = mEffectiveShadowRadius; snapshot->contentDirty = contentDirty; contentDirty = false; diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index 97c4145dd1..48a9190794 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -310,7 +310,7 @@ void LayerFE::prepareBufferStateClientComposition( void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster, const Rect& layerStackRect) const { - renderengine::ShadowSettings state = mSnapshot->shadowSettings; + ShadowSettings state = mSnapshot->shadowSettings; if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) { return; } diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 144e1f5abf..aa6026ef79 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -402,7 +402,7 @@ void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerI [&]() { return layerInfo->mutable_screen_bounds(); }); LayerProtoHelper::writeToProto(snapshot.roundedCorner.cropRect, [&]() { return layerInfo->mutable_corner_radius_crop(); }); - layerInfo->set_shadow_radius(snapshot.shadowRadius); + layerInfo->set_shadow_radius(snapshot.shadowSettings.length); layerInfo->set_id(snapshot.uniqueSequence); layerInfo->set_original_id(snapshot.sequence); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7b2d5908e6..cbea31239a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -419,7 +419,7 @@ private: bool colorMatrixChanged = true; mat4 colorMatrix; - renderengine::ShadowSettings globalShadowSettings; + ShadowSettings globalShadowSettings; void traverse(const LayerVector::Visitor& visitor) const; void traverseInZOrder(const LayerVector::Visitor& visitor) const; diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp index 23fe8fa886..c2d1954ee5 100644 --- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp +++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp @@ -56,7 +56,7 @@ bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& frontend::LayerSnapshotBuilder snapshotBuilder; ui::DisplayMap displayInfos; - renderengine::ShadowSettings globalShadowSettings{.ambientColor = {1, 1, 1, 1}}; + ShadowSettings globalShadowSettings{.ambientColor = {1, 1, 1, 1}}; char value[PROPERTY_VALUE_MAX]; property_get("ro.surface_flinger.supports_background_blur", value, "0"); bool supportsBlur = atoi(value); diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h index c47b0fc93c..d319dcc47e 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h @@ -19,6 +19,7 @@ #include #include +#include #include "Client.h" // temporarily needed for LayerCreationArgs #include "FrontEnd/LayerCreationArgs.h" @@ -488,7 +489,7 @@ protected: DisplayInfos mFrontEndDisplayInfos; bool mHasDisplayChanges = false; - renderengine::ShadowSettings globalShadowSettings; + ShadowSettings globalShadowSettings; }; } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 956c0ebca2..50dfcaac5f 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -859,7 +859,6 @@ TEST_F(LayerSnapshotTest, setShadowRadius) { setShadowRadius(1, SHADOW_RADIUS); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); EXPECT_EQ(getSnapshot(1)->shadowSettings.length, SHADOW_RADIUS); - EXPECT_EQ(getSnapshot(1)->shadowRadius, SHADOW_RADIUS); } } // namespace android::surfaceflinger::frontend -- cgit v1.2.3-59-g8ed1b From 67afbeaac2c284356f2b2aa61f48258bc0758911 Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Thu, 28 Sep 2023 15:35:07 -0700 Subject: Add smooth switch bool for setFrameRateCategory This allows the platform to have a different behavior depending on whether a device is MRR or dVRR. When the bool is `true`, MRR devices (those with DisplayModes that do not have vrr config) will not change frame rates if it would cause jank. The expected usage is to mark the bool true when an animation is running. Bug: 300491171 Test: atest libsurfaceflinger_unittest Change-Id: I5e87d276c11ecc806ede3e943f0a6498a7b910c4 --- libs/gui/LayerState.cpp | 7 +- libs/gui/SurfaceComposerClient.cpp | 3 +- libs/gui/include/gui/LayerState.h | 1 + libs/gui/include/gui/SurfaceComposerClient.h | 3 +- .../FrontEnd/RequestedLayerState.cpp | 1 + services/surfaceflinger/Layer.cpp | 6 +- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 3 +- services/surfaceflinger/Scheduler/LayerInfo.cpp | 3 +- services/surfaceflinger/Scheduler/LayerInfo.h | 3 +- .../Scheduler/RefreshRateSelector.cpp | 30 +- .../surfaceflinger/Scheduler/RefreshRateSelector.h | 14 +- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- .../tests/unittests/RefreshRateSelectorTest.cpp | 470 +++++++++++++-------- 14 files changed, 366 insertions(+), 182 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 613721e103..fd8fc8d123 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -85,6 +85,7 @@ layer_state_t::layer_state_t() changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS), defaultFrameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), frameRateCategory(ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT), + frameRateCategorySmoothSwitchOnly(false), frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF), fixedTransformHint(ui::Transform::ROT_INVALID), autoRefresh(false), @@ -162,6 +163,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeByte, changeFrameRateStrategy); SAFE_PARCEL(output.writeByte, defaultFrameRateCompatibility); SAFE_PARCEL(output.writeByte, frameRateCategory); + SAFE_PARCEL(output.writeBool, frameRateCategorySmoothSwitchOnly); SAFE_PARCEL(output.writeByte, frameRateSelectionStrategy); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeBool, autoRefresh); @@ -296,6 +298,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readByte, &changeFrameRateStrategy); SAFE_PARCEL(input.readByte, &defaultFrameRateCompatibility); SAFE_PARCEL(input.readByte, &frameRateCategory); + SAFE_PARCEL(input.readBool, &frameRateCategorySmoothSwitchOnly); SAFE_PARCEL(input.readByte, &frameRateSelectionStrategy); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); @@ -669,6 +672,7 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eFrameRateCategoryChanged) { what |= eFrameRateCategoryChanged; frameRateCategory = other.frameRateCategory; + frameRateCategorySmoothSwitchOnly = other.frameRateCategorySmoothSwitchOnly; } if (other.what & eFrameRateSelectionStrategyChanged) { what |= eFrameRateSelectionStrategyChanged; @@ -784,7 +788,8 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eFrameRateSelectionPriority, other, frameRateSelectionPriority); CHECK_DIFF3(diff, eFrameRateChanged, other, frameRate, frameRateCompatibility, changeFrameRateStrategy); - CHECK_DIFF(diff, eFrameRateCategoryChanged, other, frameRateCategory); + CHECK_DIFF2(diff, eFrameRateCategoryChanged, other, frameRateCategory, + frameRateCategorySmoothSwitchOnly); CHECK_DIFF(diff, eFrameRateSelectionStrategyChanged, other, frameRateSelectionStrategy); CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint); CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8a57f925ec..d9d99a414e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2098,7 +2098,7 @@ SurfaceComposerClient::Transaction::setDefaultFrameRateCompatibility(const sp& sc, int8_t category) { + const sp& sc, int8_t category, bool smoothSwitchOnly) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; @@ -2106,6 +2106,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame } s->what |= layer_state_t::eFrameRateCategoryChanged; s->frameRateCategory = category; + s->frameRateCategorySmoothSwitchOnly = smoothSwitchOnly; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 4371007778..d3cde74963 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -361,6 +361,7 @@ struct layer_state_t { // Frame rate category to suggest what frame rate range a surface should run. int8_t frameRateCategory; + bool frameRateCategorySmoothSwitchOnly; // Strategy of the layer for frame rate selection. int8_t frameRateSelectionStrategy; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 26b1fbd2ba..bc63c412f7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -686,7 +686,8 @@ public: Transaction& setDefaultFrameRateCompatibility(const sp& sc, int8_t compatibility); - Transaction& setFrameRateCategory(const sp& sc, int8_t category); + Transaction& setFrameRateCategory(const sp& sc, int8_t category, + bool smoothSwitchOnly); Transaction& setFrameRateSelectionStrategy(const sp& sc, int8_t strategy); diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 168267bb50..087d7c89e4 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -124,6 +124,7 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) dimmingEnabled = true; defaultFrameRateCompatibility = static_cast(scheduler::FrameRateCompatibility::Default); frameRateCategory = static_cast(FrameRateCategory::Default); + frameRateCategorySmoothSwitchOnly = false; frameRateSelectionStrategy = static_cast(scheduler::LayerInfo::FrameRateSelectionStrategy::Self); dataspace = ui::Dataspace::V0_SRGB; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2dc8758c3d..0c1c014640 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1334,13 +1334,15 @@ bool Layer::setFrameRate(FrameRate::FrameRateVote frameRateVote) { return true; } -bool Layer::setFrameRateCategory(FrameRateCategory category) { - if (mDrawingState.frameRate.category == category) { +bool Layer::setFrameRateCategory(FrameRateCategory category, bool smoothSwitchOnly) { + if (mDrawingState.frameRate.category == category && + mDrawingState.frameRate.categorySmoothSwitchOnly == smoothSwitchOnly) { return false; } mDrawingState.sequence++; mDrawingState.frameRate.category = category; + mDrawingState.frameRate.categorySmoothSwitchOnly = smoothSwitchOnly; mDrawingState.modified = true; updateTreeHasFrameRateVote(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 0b66866158..1b9925539b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -783,7 +783,7 @@ public: Rect getCroppedBufferSize(const Layer::State& s) const; bool setFrameRate(FrameRate::FrameRateVote); - bool setFrameRateCategory(FrameRateCategory); + bool setFrameRateCategory(FrameRateCategory, bool smoothSwitchOnly); bool setFrameRateSelectionStrategy(FrameRateSelectionStrategy); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 4e5659ec5a..069d89bc42 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -194,7 +194,8 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - to_string(vote.fps).c_str(), categoryString.c_str(), weight * 100); summary.push_back({info->getName(), info->getOwnerUid(), vote.type, vote.fps, - vote.seamlessness, vote.category, weight, layerFocused}); + vote.seamlessness, vote.category, vote.categorySmoothSwitchOnly, + weight, layerFocused}); if (CC_UNLIKELY(mTraceEnabled)) { trace(*info, vote.type, vote.fps.getIntValue()); diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index dd96930a06..36f2475d8e 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -309,7 +309,8 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec ALOGV("%s uses frame rate category: %d", mName.c_str(), static_cast(mLayerVote.category)); votes.push_back({LayerHistory::LayerVoteType::ExplicitCategory, Fps(), - Seamlessness::Default, mLayerVote.category}); + Seamlessness::Default, mLayerVote.category, + mLayerVote.categorySmoothSwitchOnly}); } if (mLayerVote.fps.isValid() || diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index d580b58f53..7d3cffabf7 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -71,8 +71,8 @@ public: LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic; Fps fps; Seamlessness seamlessness = Seamlessness::Default; - // Category is in effect if fps is not specified. FrameRateCategory category = FrameRateCategory::Default; + bool categorySmoothSwitchOnly = false; // Returns true if the layer explicitly should contribute to frame rate scoring. bool isNoVote() const { return RefreshRateSelector::isNoVote(type); } @@ -111,6 +111,7 @@ public: } vote; FrameRateCategory category = FrameRateCategory::Default; + bool categorySmoothSwitchOnly = false; FrameRate() = default; diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index b06723ddab..1d23fb5f38 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -494,6 +494,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector 0 || @@ -578,10 +582,17 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector 0; + const DisplayModeId activeModeId = activeMode.getId(); + // Only if all layers want Min we should return Min if (noVoteLayers + minVoteLayers == layers.size()) { ALOGV("All layers Min"); - const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending); + const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending, + std::nullopt, [&](FrameRateMode mode) { + return !smoothSwitchOnly || + mode.modePtr->getId() == activeModeId; + }); ATRACE_FORMAT_INSTANT("%s (All layers Min)", to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals}; @@ -627,6 +638,14 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vectorgetId() != activeModeId) { + ALOGV("%s ignores %s because it's non-VRR and smooth switch only." + " Current mode = %s", + formatLayerInfo(layer, weight).c_str(), to_string(*modePtr).c_str(), + to_string(activeMode).c_str()); + continue; + } + // Layers with default seamlessness vote for the current mode group if // there are layers with seamlessness=SeamedAndSeamless and for the default // mode group otherwise. In second case, if the current mode group is different @@ -770,6 +789,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector anchorGroupOpt, RefreshRateOrder refreshRateOrder, - std::optional preferredDisplayModeOpt) const + std::optional preferredDisplayModeOpt, + const RankFrameRatesPredicate& predicate) const -> FrameRateRanking { using fps_approx_ops::operator<; const char* const whence = __func__; @@ -1044,7 +1067,8 @@ auto RefreshRateSelector::rankFrameRates(std::optional anchorGroupOpt, std::deque ranking; const auto rankFrameRate = [&](const FrameRateMode& frameRateMode) REQUIRES(mLock) { const auto& modePtr = frameRateMode.modePtr; - if (anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) { + if ((anchorGroupOpt && modePtr->getGroup() != anchorGroupOpt) || + !predicate(frameRateMode)) { return; } diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 5d32414ee5..545b939b3d 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -170,8 +170,11 @@ public: Fps desiredRefreshRate; // If a seamless mode switch is required. Seamlessness seamlessness = Seamlessness::Default; - // Layer frame rate category. Superseded by desiredRefreshRate. + // Layer frame rate category. FrameRateCategory frameRateCategory = FrameRateCategory::Default; + // Goes together with frame rate category vote. Allow refresh rate changes only + // if there would be no jank. + bool frameRateCategorySmoothSwitchOnly = false; // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer // would have on choosing the refresh rate. float weight = 0.0f; @@ -446,10 +449,15 @@ private: ftl_last = Descending }; - // Only uses the primary range, not the app request range. + typedef std::function RankFrameRatesPredicate; + + // Rank the frame rates. + // Only modes in the primary range for which `predicate` is `true` will be scored. + // Does not use the app requested range. FrameRateRanking rankFrameRates( std::optional anchorGroupOpt, RefreshRateOrder refreshRateOrder, - std::optional preferredDisplayModeOpt = std::nullopt) const + std::optional preferredDisplayModeOpt = std::nullopt, + const RankFrameRatesPredicate& predicate = [](FrameRateMode) { return true; }) const REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7e799bbe30..3d3c1690a1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5228,7 +5228,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } if (what & layer_state_t::eFrameRateCategoryChanged) { const FrameRateCategory category = Layer::FrameRate::convertCategory(s.frameRateCategory); - if (layer->setFrameRateCategory(category)) { + if (layer->setFrameRateCategory(category, s.frameRateCategorySmoothSwitchOnly)) { flags |= eTraversalNeeded; } } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index 0b671376f8..faa12a1032 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -117,9 +117,9 @@ struct TestableRefreshRateSelector : RefreshRateSelector { return std::make_pair(ranking, consideredSignals); } - ftl::NonNull getBestFrameRateMode( - const std::vector& layers = {}, GlobalSignals signals = {}) const { - return getRankedFrameRates(layers, signals).ranking.front().frameRateMode.modePtr; + FrameRateMode getBestFrameRateMode(const std::vector& layers = {}, + GlobalSignals signals = {}) const { + return getRankedFrameRates(layers, signals).ranking.front().frameRateMode; } ScoredFrameRate getBestScoredFrameRate(const std::vector& layers = {}, @@ -429,11 +429,11 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_noLayers) { // If there are no layers we select the default frame rate, which is the max of the primary // range. - EXPECT_EQ(kMode90, selector.getBestFrameRateMode()); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode().modePtr); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}})); - EXPECT_EQ(kMode60, selector.getBestFrameRateMode()); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode().modePtr); } { // We select max even when this will cause a non-seamless switch. @@ -442,7 +442,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_noLayers) { EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy( {kModeId90, {0_Hz, 90_Hz}, kAllowGroupSwitching})); - EXPECT_EQ(kMode90_G1, selector.getBestFrameRateMode()); + EXPECT_EQ(kMode90_G1, selector.getBestFrameRateMode().modePtr); } } @@ -455,7 +455,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_exactDontChangeRefreshRateW EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId72, {0_Hz, 90_Hz}})); - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_90) { @@ -466,107 +466,107 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_90) { lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; lr.name = "45Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; lr.name = "30Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; lr.name = "24Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.name = ""; EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {60_Hz, 60_Hz}})); lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}})); lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 120_Hz}})); lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_multipleThreshold_60_90) { @@ -577,32 +577,32 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_multipleThreshold_60_90) { lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; lr.name = "45Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; lr.name = "30Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; lr.name = "24Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_72_90) { @@ -612,26 +612,26 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_60_72_90) { auto& lr = layers[0]; lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90_120) { @@ -645,19 +645,19 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90_120) { lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48_Hz; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 48_Hz; lr2.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes) { @@ -673,7 +673,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -681,7 +681,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -689,7 +689,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -697,7 +697,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -705,7 +705,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -713,7 +713,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; @@ -721,7 +721,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -729,7 +729,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -737,7 +737,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_90_120_DifferentTypes lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, @@ -756,7 +756,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -764,7 +764,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -772,7 +772,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -780,7 +780,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -788,7 +788,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -796,7 +796,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::Heuristic; @@ -804,7 +804,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -812,7 +812,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitDefault; @@ -820,14 +820,14 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -835,7 +835,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 120_Hz; lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "120Hz ExplicitDefault"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 24_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -843,7 +843,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 120_Hz; lr2.vote = LayerVoteType::ExplicitExact; lr2.name = "120Hz ExplicitExact"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 10_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -851,7 +851,7 @@ TEST_P(RefreshRateSelectorTest, lr2.desiredRefreshRate = 120_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.name = "120Hz ExplicitExact"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); lr1.desiredRefreshRate = 30_Hz; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -862,7 +862,7 @@ TEST_P(RefreshRateSelectorTest, lr3.vote = LayerVoteType::Heuristic; lr3.desiredRefreshRate = 120_Hz; lr3.name = "120Hz Heuristic"; - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60) { @@ -872,26 +872,26 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60) { auto& lr = layers[0]; lr.vote = LayerVoteType::Min; - EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90) { @@ -902,42 +902,42 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_30_60_72_90) { lr.vote = LayerVoteType::Min; lr.name = "Min"; - EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; lr.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 90_Hz; lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); lr.desiredRefreshRate = 45_Hz; lr.name = "45Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); lr.desiredRefreshRate = 30_Hz; lr.name = "30Hz Heuristic"; - EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers)); - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode30, selector.getBestFrameRateMode(layers).modePtr); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); lr.desiredRefreshRate = 24_Hz; lr.name = "24Hz Heuristic"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); lr.desiredRefreshRate = 24_Hz; lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.name = "24Hz ExplicitExactOrMultiple"; - EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers)); - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode72, selector.getBestFrameRateMode(layers).modePtr); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_PriorityTest) { @@ -949,39 +949,39 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_PriorityTest) { lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Max; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 24_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 15_Hz; lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 30_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 45_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo) { @@ -993,7 +993,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { lr.desiredRefreshRate = Fps::fromValue(fps); - const auto mode = selector.getBestFrameRateMode(layers); + const auto mode = selector.getBestFrameRateMode(layers).modePtr; EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses " << to_string(mode->getPeakFps()) << "(" << to_string(mode->getVsyncRate()) << ")"; @@ -1009,7 +1009,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo_multipleThreshol lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { lr.desiredRefreshRate = Fps::fromValue(fps); - const auto mode = selector.getBestFrameRateMode(layers); + const auto mode = selector.getBestFrameRateMode(layers).modePtr; EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses " << to_string(mode->getPeakFps()) << "(" << to_string(mode->getVsyncRate()) << ")"; @@ -1027,19 +1027,19 @@ TEST_P(RefreshRateSelectorTest, twoModes_getBestFrameRateMode_Explicit) { lr1.desiredRefreshRate = 60_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 90_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::ExplicitDefault; lr1.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::Heuristic; lr1.desiredRefreshRate = 90_Hz; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.desiredRefreshRate = 60_Hz; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_75HzContent) { @@ -1051,7 +1051,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_75HzContent) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) { lr.desiredRefreshRate = Fps::fromValue(fps); - const auto mode = selector.getBestFrameRateMode(layers, {}); + const auto mode = selector.getBestFrameRateMode(layers, {}).modePtr; EXPECT_EQ(kMode90, mode) << lr.desiredRefreshRate << " chooses " << to_string(mode->getPeakFps()) << "(" << to_string(mode->getVsyncRate()) << ")"; @@ -1071,7 +1071,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_Multiples) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; @@ -1079,14 +1079,14 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_Multiples) { lr2.vote = LayerVoteType::ExplicitDefault; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz ExplicitDefault"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 30_Hz; @@ -1094,14 +1094,14 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_Multiples) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 30_Hz; lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { @@ -1116,28 +1116,28 @@ TEST_P(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.desiredRefreshRate = 60_Hz; lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); // The other layer starts to provide buffers lr1.vote = LayerVoteType::ExplicitExactOrMultiple; @@ -1146,7 +1146,7 @@ TEST_P(RefreshRateSelectorTest, scrollWhileWatching60fps_60_90) { lr2.vote = LayerVoteType::Heuristic; lr2.desiredRefreshRate = 90_Hz; lr2.name = "90Hz Heuristic"; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicy) { @@ -1464,7 +1464,8 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60 layers.push_back(layer); } - EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps()) + EXPECT_EQ(testCase.expectedFrameRate, + selector.getBestFrameRateMode(layers).modePtr->getPeakFps()) << "Did not get expected frame rate for frameRate=" << to_string(testCase.desiredFrameRate) << " category=" << ftl::enum_string(testCase.frameRateCategory); @@ -1528,13 +1529,147 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_60_12 layers.push_back(layer); } - EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps()) + EXPECT_EQ(testCase.expectedFrameRate, + selector.getBestFrameRateMode(layers).modePtr->getPeakFps()) << "Did not get expected frame rate for frameRate=" << to_string(testCase.desiredFrameRate) << " category=" << ftl::enum_string(testCase.frameRateCategory); } } +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_nonVrr) { + if (GetParam() != Config::FrameRateOverride::Enabled) { + return; + } + + // VRR compatibility is determined by the presence of a vrr config in the DisplayMode. + auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120); + + struct Case { + // Params + FrameRateCategory frameRateCategory = FrameRateCategory::Default; + bool smoothSwitchOnly = false; + + // Expected result + Fps expectedFrameRate = 0_Hz; + DisplayModeId expectedModeId = kModeId60; + }; + + const std::initializer_list testCases = { + // These layers may switch modes because smoothSwitchOnly=false. + {FrameRateCategory::Default, false, 120_Hz, kModeId120}, + // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate. + {FrameRateCategory::NoPreference, false, 60_Hz, kModeId60}, + {FrameRateCategory::Low, false, 30_Hz, kModeId60}, + {FrameRateCategory::Normal, false, 60_Hz, kModeId60}, + {FrameRateCategory::High, false, 120_Hz, kModeId120}, + + // These layers cannot change mode due to smoothSwitchOnly, and will definitely use + // active mode (120Hz). + {FrameRateCategory::NoPreference, true, 120_Hz, kModeId120}, + {FrameRateCategory::Low, true, 40_Hz, kModeId120}, + {FrameRateCategory::Normal, true, 40_Hz, kModeId120}, + {FrameRateCategory::High, true, 120_Hz, kModeId120}, + }; + + for (auto testCase : testCases) { + std::vector layers; + ALOGI("**** %s: Testing frameRateCategory=%s (smooth=%d)", __func__, + ftl::enum_string(testCase.frameRateCategory).c_str(), testCase.smoothSwitchOnly); + + if (testCase.frameRateCategory != FrameRateCategory::Default) { + std::stringstream ss; + ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory) + << " smooth:" << testCase.smoothSwitchOnly << ")"; + LayerRequirement layer = {.name = ss.str(), + .vote = LayerVoteType::ExplicitCategory, + .frameRateCategory = testCase.frameRateCategory, + .frameRateCategorySmoothSwitchOnly = + testCase.smoothSwitchOnly, + .weight = 1.f}; + layers.push_back(layer); + } + + auto actualFrameRateMode = selector.getBestFrameRateMode(layers); + EXPECT_EQ(testCase.expectedFrameRate, actualFrameRateMode.fps) + << "Did not get expected frame rate for category=" + << ftl::enum_string(testCase.frameRateCategory) + << " (smooth=" << testCase.smoothSwitchOnly << ")"; + + EXPECT_EQ(testCase.expectedModeId, actualFrameRateMode.modePtr->getId()) + << "Did not get expected mode for category=" + << ftl::enum_string(testCase.frameRateCategory) + << " (smooth=" << testCase.smoothSwitchOnly << ")"; + } +} + +TEST_P(RefreshRateSelectorTest, + getBestFrameRateMode_withFrameRateCategory_smoothSwitchOnly_60_120_vrr) { + if (GetParam() != Config::FrameRateOverride::Enabled) { + return; + } + + // VRR compatibility is determined by the presence of a vrr config in the DisplayMode. + auto selector = createSelector(kVrrModes_60_120, kModeId120); + + struct Case { + // Params + FrameRateCategory frameRateCategory = FrameRateCategory::Default; + bool smoothSwitchOnly = false; + + // Expected result + Fps expectedFrameRate = 0_Hz; + }; + + // Note that `smoothSwitchOnly` should not have an effect. + const std::initializer_list testCases = { + {FrameRateCategory::Default, false, 240_Hz}, + // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate. + {FrameRateCategory::NoPreference, false, 240_Hz}, + {FrameRateCategory::Low, false, 30_Hz}, + {FrameRateCategory::Normal, false, 60_Hz}, + {FrameRateCategory::High, false, 120_Hz}, + {FrameRateCategory::Default, true, 240_Hz}, + // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate. + {FrameRateCategory::NoPreference, true, 240_Hz}, + {FrameRateCategory::Low, true, 30_Hz}, + {FrameRateCategory::Normal, true, 60_Hz}, + {FrameRateCategory::High, true, 120_Hz}, + }; + + for (auto testCase : testCases) { + std::vector layers; + ALOGI("**** %s: Testing frameRateCategory=%s (smooth=%d)", __func__, + ftl::enum_string(testCase.frameRateCategory).c_str(), testCase.smoothSwitchOnly); + + if (testCase.frameRateCategory != FrameRateCategory::Default) { + std::stringstream ss; + ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory) + << " smooth:" << testCase.smoothSwitchOnly << ")"; + LayerRequirement layer = {.name = ss.str(), + .vote = LayerVoteType::ExplicitCategory, + .frameRateCategory = testCase.frameRateCategory, + .frameRateCategorySmoothSwitchOnly = + testCase.smoothSwitchOnly, + .weight = 1.f}; + layers.push_back(layer); + } + + auto actualFrameRateMode = selector.getBestFrameRateMode(layers); + EXPECT_EQ(testCase.expectedFrameRate, actualFrameRateMode.fps) + << "Did not get expected frame rate for category=" + << ftl::enum_string(testCase.frameRateCategory) + << " (smooth=" << testCase.smoothSwitchOnly << ")"; + + // Expect all cases to be able to stay at the mode with TE 240 due to VRR compatibility. + EXPECT_EQ(kVrrMode120TE240->getId(), actualFrameRateMode.modePtr->getId()) + << "Did not get expected mode for category=" + << ftl::enum_string(testCase.frameRateCategory) + << " (smooth=" << testCase.smoothSwitchOnly << ")"; + } +} + TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitDefault) { auto selector = createSelector(kModes_60_90_72_120, kModeId60); @@ -1568,7 +1703,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitDefault) { ss << "ExplicitDefault " << desired; lr.name = ss.str(); - const auto bestMode = selector.getBestFrameRateMode(layers); + const auto bestMode = selector.getBestFrameRateMode(layers).modePtr; EXPECT_EQ(expected, bestMode->getPeakFps()) << "expected " << expected << " for " << desired << " but got " << bestMode->getPeakFps() << "(" << bestMode->getVsyncRate() << ")"; @@ -1589,7 +1724,7 @@ TEST_P(RefreshRateSelectorTest, lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.desiredRefreshRate = 23.976_Hz; lr.name = "ExplicitExactOrMultiple 23.976 Hz"; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } // Test that 24 will choose 23.976 if 24 is not supported @@ -1600,7 +1735,7 @@ TEST_P(RefreshRateSelectorTest, lr.desiredRefreshRate = 24_Hz; lr.name = "ExplicitExactOrMultiple 24 Hz"; - EXPECT_EQ(kModeId24Frac, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId24Frac, selector.getBestFrameRateMode(layers).modePtr->getId()); } // Test that 29.97 will prefer 59.94 over 60 and 30 @@ -1611,7 +1746,7 @@ TEST_P(RefreshRateSelectorTest, lr.desiredRefreshRate = 29.97_Hz; lr.name = "ExplicitExactOrMultiple 29.97 Hz"; - EXPECT_EQ(kModeId60Frac, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60Frac, selector.getBestFrameRateMode(layers).modePtr->getId()); } // Test that 29.97 will choose 60 if 59.94 is not supported @@ -1620,7 +1755,7 @@ TEST_P(RefreshRateSelectorTest, lr.desiredRefreshRate = 29.97_Hz; lr.name = "ExplicitExactOrMultiple 29.97 Hz"; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } // Test that 59.94 will choose 60 if 59.94 is not supported @@ -1629,7 +1764,7 @@ TEST_P(RefreshRateSelectorTest, lr.desiredRefreshRate = 59.94_Hz; lr.name = "ExplicitExactOrMultiple 59.94 Hz"; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } } @@ -1648,7 +1783,8 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitExact_WithFractiona ss << "ExplicitExact " << desired; lr.name = ss.str(); - EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getPeakFps()); + EXPECT_EQ(lr.desiredRefreshRate, + selector.getBestFrameRateMode(layers).modePtr->getPeakFps()); } } } @@ -1694,7 +1830,7 @@ TEST_P(RefreshRateSelectorTest, lr.desiredRefreshRate = 90_Hz; lr.name = "90Hz ExplicitDefault"; lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.idle = true})); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers, {.idle = true}).modePtr); } TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) { @@ -1905,46 +2041,46 @@ TEST_P(RefreshRateSelectorTest, lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz ExplicitExactOrMultiple"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::ExplicitDefault; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz ExplicitDefault"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.focused = true; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Heuristic; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Heuristic"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Max; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Max"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.vote = LayerVoteType::Min; lr.desiredRefreshRate = 60_Hz; lr.name = "60Hz Min"; lr.focused = false; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); lr.focused = true; - EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode90, selector.getBestFrameRateMode(layers).modePtr); } TEST_P(RefreshRateSelectorTest, groupSwitchingNotAllowed) { @@ -1960,7 +2096,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingNotAllowed) { layer.name = "90Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayer) { @@ -1978,7 +2114,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayer) { layer.seamlessness = Seamlessness::SeamedAndSeamless; layer.name = "90Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamless) { @@ -1997,7 +2133,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamless) { layer.seamlessness = Seamlessness::OnlySeamless; layer.name = "90Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps) { @@ -2018,7 +2154,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerOnlySeamlessDefaultFps layer.seamlessness = Seamlessness::OnlySeamless; layer.name = "60Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerDefaultSeamlessness) { @@ -2042,7 +2178,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithOneLayerDefaultSeamlessness) { layer.name = "60Hz ExplicitDefault"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed) { @@ -2071,7 +2207,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersOnlySeamlessAndSeamed layers[1].name = "90Hz ExplicitDefault"; layers[1].focused = false; - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeamed) { @@ -2104,7 +2240,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultFocusedAndSeam layers[1].vote = LayerVoteType::ExplicitDefault; layers[1].name = "90Hz ExplicitDefault"; - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndSeamed) { @@ -2134,7 +2270,7 @@ TEST_P(RefreshRateSelectorTest, groupSwitchingWithTwoLayersDefaultNotFocusedAndS layers[1].vote = LayerVoteType::ExplicitDefault; layers[1].name = "90Hz ExplicitDefault"; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, nonSeamlessVotePrefersSeamlessSwitches) { @@ -2154,10 +2290,10 @@ TEST_P(RefreshRateSelectorTest, nonSeamlessVotePrefersSeamlessSwitches) { layer.name = "60Hz ExplicitExactOrMultiple"; layer.focused = true; - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode(layers).modePtr->getId()); selector.setActiveMode(kModeId120, 120_Hz); - EXPECT_EQ(kModeId120, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId120, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, nonSeamlessExactAndSeamlessMultipleLayers) { @@ -2182,14 +2318,14 @@ TEST_P(RefreshRateSelectorTest, nonSeamlessExactAndSeamlessMultipleLayers) { .weight = 1.f, .focused = true}}; - EXPECT_EQ(kModeId50, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId50, selector.getBestFrameRateMode(layers).modePtr->getId()); auto& seamedLayer = layers[0]; seamedLayer.desiredRefreshRate = 30_Hz; seamedLayer.name = "30Hz ExplicitDefault"; selector.setActiveMode(kModeId30, 30_Hz); - EXPECT_EQ(kModeId25, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId25, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, minLayersDontTrigerSeamedSwitch) { @@ -2204,7 +2340,7 @@ TEST_P(RefreshRateSelectorTest, minLayersDontTrigerSeamedSwitch) { std::vector layers = { {.name = "Min", .vote = LayerVoteType::Min, .weight = 1.f, .focused = true}}; - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers)->getId()); + EXPECT_EQ(kModeId90, selector.getBestFrameRateMode(layers).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { @@ -2225,7 +2361,7 @@ TEST_P(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { layers[0].vote = voteType; layers[0].desiredRefreshRate = fps; layers[0].focused = args.focused; - return selector.getBestFrameRateMode(layers, {.touch = args.touch})->getId(); + return selector.getBestFrameRateMode(layers, {.touch = args.touch}).modePtr->getId(); }; constexpr FpsRange k30_60 = {30_Hz, 60_Hz}; @@ -2234,7 +2370,7 @@ TEST_P(RefreshRateSelectorTest, primaryVsAppRequestPolicy) { EXPECT_EQ(SetPolicyResult::Changed, selector.setDisplayManagerPolicy({kModeId60, {k30_60, k30_60}, {k30_90, k30_90}})); - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode()->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode().modePtr->getId()); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::NoVote, 90_Hz)); EXPECT_EQ(kModeId30, getFrameRate(LayerVoteType::Min, 90_Hz)); EXPECT_EQ(kModeId60, getFrameRate(LayerVoteType::Max, 90_Hz)); @@ -2302,7 +2438,8 @@ TEST_P(RefreshRateSelectorTest, idle) { } // With no layers, idle should still be lower priority than touch boost. - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode({}, {.touch = true, .idle = true})->getId()); + EXPECT_EQ(kModeId90, + selector.getBestFrameRateMode({}, {.touch = true, .idle = true}).modePtr->getId()); // Idle should be higher precedence than other layer frame rate considerations. selector.setActiveMode(kModeId90, 90_Hz); @@ -2319,7 +2456,7 @@ TEST_P(RefreshRateSelectorTest, idle) { } // Idle should be applied rather than the active mode when there are no layers. - EXPECT_EQ(kModeId60, selector.getBestFrameRateMode({}, {.idle = true})->getId()); + EXPECT_EQ(kModeId60, selector.getBestFrameRateMode({}, {.idle = true}).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, findClosestKnownFrameRate) { @@ -2368,7 +2505,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_KnownFrameRate) { for (const auto& [fps, mode] : knownFrameRatesExpectations) { layer.desiredRefreshRate = fps; - EXPECT_EQ(mode, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(mode, selector.getBestFrameRateMode(layers).modePtr); } } @@ -2471,17 +2608,17 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitExactTouchBoost) { explicitExactLayer.name = "ExplicitExact"; explicitExactLayer.desiredRefreshRate = 30_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); if (GetParam() == Config::FrameRateOverride::Disabled) { - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); } else { - EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode120, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); } explicitExactOrMultipleLayer.vote = LayerVoteType::NoVote; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true})); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers, {.touch = true}).modePtr); } TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_FractionalRefreshRates_ExactAndDefault) { @@ -2499,7 +2636,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_FractionalRefreshRates_Exac explicitDefaultLayer.name = "ExplicitDefault"; explicitDefaultLayer.desiredRefreshRate = 59.94_Hz; - EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers)); + EXPECT_EQ(kMode60, selector.getBestFrameRateMode(layers).modePtr); } // b/190578904 @@ -2526,7 +2663,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withCloseRefreshRates) { layers[0].desiredRefreshRate = fps; layers[0].vote = vote; EXPECT_EQ(fps.getIntValue(), - selector.getBestFrameRateMode(layers)->getPeakFps().getIntValue()) + selector.getBestFrameRateMode(layers).modePtr->getPeakFps().getIntValue()) << "Failed for " << ftl::enum_string(vote); }; @@ -2565,7 +2702,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_conflictingVotes) { }, }; - EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getPeakFps()); + EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals).modePtr->getPeakFps()); } TEST_P(RefreshRateSelectorTest, modeComparison) { @@ -3176,7 +3313,8 @@ TEST_P(RefreshRateSelectorTest, idleWhenLowestRefreshRateIsNotDivisor) { selector.setDisplayManagerPolicy({kModeId60, {0_Hz, 90_Hz}})); // With no layers, idle should still be lower priority than touch boost. - EXPECT_EQ(kModeId90, selector.getBestFrameRateMode({}, {.touch = true, .idle = true})->getId()); + EXPECT_EQ(kModeId90, + selector.getBestFrameRateMode({}, {.touch = true, .idle = true}).modePtr->getId()); // Idle should be higher precedence than other layer frame rate considerations. selector.setActiveMode(kModeId90, 90_Hz); @@ -3192,7 +3330,7 @@ TEST_P(RefreshRateSelectorTest, idleWhenLowestRefreshRateIsNotDivisor) { } // Idle should be applied rather than the active mode when there are no layers. - EXPECT_EQ(kModeId35, selector.getBestFrameRateMode({}, {.idle = true})->getId()); + EXPECT_EQ(kModeId35, selector.getBestFrameRateMode({}, {.idle = true}).modePtr->getId()); } TEST_P(RefreshRateSelectorTest, policyCanBeInfinity) { -- cgit v1.2.3-59-g8ed1b From f3621106fc277a0b16609927e81a47aca87c22c6 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Mon, 4 Sep 2023 17:14:22 +0800 Subject: VRR: Use appId to replace uid mapping Uid is combination of user id and app id. Because the allowlist is recored by pkg for each users. We could ignore the user id part and it also could solve the issue we didn't update the mapping when user added case. Bug: 298722189 Test: atest SmallAreaDetectionAllowMappingsTest Test: atest SmallAreaDetectionControllerTest Test: Add new user and open Youtube short to check refresh rate Change-Id: Ic80be38ebc19938bc061bf6121c68efc4ff9ac4c --- libs/gui/SurfaceComposerClient.cpp | 8 ++--- libs/gui/aidl/android/gui/ISurfaceComposer.aidl | 8 ++--- libs/gui/include/gui/SurfaceComposerClient.h | 10 +++--- libs/gui/tests/Surface_test.cpp | 4 +-- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 8 +++++ services/surfaceflinger/Scheduler/Scheduler.cpp | 15 ++++----- services/surfaceflinger/Scheduler/Scheduler.h | 6 ++-- .../Scheduler/SmallAreaDetectionAllowMappings.cpp | 12 ++++---- .../Scheduler/SmallAreaDetectionAllowMappings.h | 10 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 22 ++++++------- services/surfaceflinger/SurfaceFlinger.h | 8 ++--- .../SmallAreaDetectionAllowMappingsTest.cpp | 36 ++++++++++------------ 13 files changed, 78 insertions(+), 72 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4db960e7fa..d23b9e66a9 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2768,16 +2768,16 @@ status_t SurfaceComposerClient::setOverrideFrameRate(uid_t uid, float frameRate) return statusTFromBinderStatus(status); } -status_t SurfaceComposerClient::updateSmallAreaDetection(std::vector& uids, +status_t SurfaceComposerClient::updateSmallAreaDetection(std::vector& appIds, std::vector& thresholds) { binder::Status status = - ComposerServiceAIDL::getComposerService()->updateSmallAreaDetection(uids, thresholds); + ComposerServiceAIDL::getComposerService()->updateSmallAreaDetection(appIds, thresholds); return statusTFromBinderStatus(status); } -status_t SurfaceComposerClient::setSmallAreaDetectionThreshold(uid_t uid, float threshold) { +status_t SurfaceComposerClient::setSmallAreaDetectionThreshold(int32_t appId, float threshold) { binder::Status status = - ComposerServiceAIDL::getComposerService()->setSmallAreaDetectionThreshold(uid, + ComposerServiceAIDL::getComposerService()->setSmallAreaDetectionThreshold(appId, threshold); return statusTFromBinderStatus(status); } diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index 1c604a1f8b..2c8b4b83ca 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -479,14 +479,14 @@ interface ISurfaceComposer { */ void setOverrideFrameRate(int uid, float frameRate); - oneway void updateSmallAreaDetection(in int[] uids, in float[] thresholds); + oneway void updateSmallAreaDetection(in int[] appIds, in float[] thresholds); /** - * Set the small area detection threshold for a specified uid by SmallAreaDetectionController. - * Passing the threshold and uid to SurfaceFlinger to update the uid-threshold mapping + * Set the small area detection threshold for a specified appId by SmallAreaDetectionController. + * Passing the threshold and appId to SurfaceFlinger to update the appId-threshold mapping * in the scheduler. */ - oneway void setSmallAreaDetectionThreshold(int uid, float threshold); + oneway void setSmallAreaDetectionThreshold(int appId, float threshold); /** * Enables or disables the frame rate overlay in the top left corner. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6fef5d2378..cb48807207 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -203,15 +203,15 @@ public: // by GameManager. static status_t setOverrideFrameRate(uid_t uid, float frameRate); - // Update the small area detection whole uid-threshold mappings by same size uid and threshold - // vector. + // Update the small area detection whole appId-threshold mappings by same size appId and + // threshold vector. // Ref:setSmallAreaDetectionThreshold. - static status_t updateSmallAreaDetection(std::vector& uids, + static status_t updateSmallAreaDetection(std::vector& appIds, std::vector& thresholds); - // Sets the small area detection threshold to particular apps (uid). Passing value 0 means + // Sets the small area detection threshold to particular apps (appId). Passing value 0 means // to disable small area detection to the app. - static status_t setSmallAreaDetectionThreshold(uid_t uid, float threshold); + static status_t setSmallAreaDetectionThreshold(int32_t appId, float threshold); // Switches on/off Auto Low Latency Mode on the connected display. This should only be // called if the connected display supports Auto Low Latency Mode as reported by diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index daed764cd6..edd95bad6d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -999,12 +999,12 @@ public: binder::Status scheduleCommit() override { return binder::Status::ok(); } - binder::Status updateSmallAreaDetection(const std::vector& /*uids*/, + binder::Status updateSmallAreaDetection(const std::vector& /*appIds*/, const std::vector& /*thresholds*/) { return binder::Status::ok(); } - binder::Status setSmallAreaDetectionThreshold(int32_t /*uid*/, float /*threshold*/) { + binder::Status setSmallAreaDetectionThreshold(int32_t /*appId*/, float /*threshold*/) { return binder::Status::ok(); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 9a5173ba9b..6b5613849a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -205,6 +205,7 @@ Layer::Layer(const surfaceflinger::LayerCreationArgs& args) mOwnerUid = args.ownerUid; mOwnerPid = args.ownerPid; + mOwnerAppId = mOwnerUid % PER_USER_RANGE; mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow; @@ -4388,7 +4389,7 @@ void Layer::setIsSmallDirty() { // If the damage region is a small dirty, this could give the hint for the layer history that // it could suppress the heuristic rate when calculating. - mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerUid, + mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerAppId, bounds.getWidth() * bounds.getHeight()); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index dc4ceb0bfa..e67a290d50 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -831,6 +831,8 @@ public: pid_t getOwnerPid() { return mOwnerPid; } + int32_t getOwnerAppId() { return mOwnerAppId; } + // This layer is not a clone, but it's the parent to the cloned hierarchy. The // variable mClonedChild represents the top layer that will be cloned so this // layer will be the parent of mClonedChild. @@ -1056,6 +1058,8 @@ protected: // If created from a system process, the value can be passed in. pid_t mOwnerPid; + int32_t mOwnerAppId; + // Keeps track of the time SF latched the last buffer from this layer. // Used in buffer stuffing analysis in FrameTimeline. nsecs_t mLastLatchTime = 0; @@ -1065,6 +1069,10 @@ protected: sp mLastClientCompositionFence; bool mClearClientCompositionFenceOnLayerDisplayed = false; private: + // Range of uids allocated for a user. + // This value is taken from android.os.UserHandle#PER_USER_RANGE. + static constexpr int32_t PER_USER_RANGE = 100000; + friend class SlotGenerationTest; friend class TransactionFrameTracerTest; friend class TransactionSurfaceFrameTest; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 27c96f7d4f..09ce9a68e8 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -1180,18 +1180,19 @@ void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverrid } void Scheduler::updateSmallAreaDetection( - std::vector>& uidThresholdMappings) { + std::vector>& uidThresholdMappings) { mSmallAreaDetectionAllowMappings.update(uidThresholdMappings); } -void Scheduler::setSmallAreaDetectionThreshold(uid_t uid, float threshold) { - mSmallAreaDetectionAllowMappings.setThesholdForUid(uid, threshold); +void Scheduler::setSmallAreaDetectionThreshold(int32_t appId, float threshold) { + mSmallAreaDetectionAllowMappings.setThesholdForAppId(appId, threshold); } -bool Scheduler::isSmallDirtyArea(uid_t uid, uint32_t dirtyArea) { - std::optional oThreshold = mSmallAreaDetectionAllowMappings.getThresholdForUid(uid); - if (oThreshold) return mLayerHistory.isSmallDirtyArea(dirtyArea, oThreshold.value()); - +bool Scheduler::isSmallDirtyArea(int32_t appId, uint32_t dirtyArea) { + std::optional oThreshold = mSmallAreaDetectionAllowMappings.getThresholdForAppId(appId); + if (oThreshold) { + return mLayerHistory.isSmallDirtyArea(dirtyArea, oThreshold.value()); + } return false; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index d65df2a65d..23a21e8170 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -292,12 +292,12 @@ public: void setGameModeRefreshRateForUid(FrameRateOverride); - void updateSmallAreaDetection(std::vector>& uidThresholdMappings); + void updateSmallAreaDetection(std::vector>& uidThresholdMappings); - void setSmallAreaDetectionThreshold(uid_t uid, float threshold); + void setSmallAreaDetectionThreshold(int32_t appId, float threshold); // Returns true if the dirty area is less than threshold. - bool isSmallDirtyArea(uid_t uid, uint32_t dirtyArea); + bool isSmallDirtyArea(int32_t appId, uint32_t dirtyArea); // Retrieves the overridden refresh rate for a given uid. std::optional getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock); diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp index 95cd5d199a..38c6da48f6 100644 --- a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp +++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp @@ -19,26 +19,26 @@ namespace android::scheduler { void SmallAreaDetectionAllowMappings::update( - std::vector>& uidThresholdMappings) { + std::vector>& appIdThresholdMappings) { std::lock_guard lock(mLock); mMap.clear(); - for (std::pair row : uidThresholdMappings) { + for (std::pair row : appIdThresholdMappings) { if (!isValidThreshold(row.second)) continue; mMap.emplace(row.first, row.second); } } -void SmallAreaDetectionAllowMappings::setThesholdForUid(uid_t uid, float threshold) { +void SmallAreaDetectionAllowMappings::setThesholdForAppId(int32_t appId, float threshold) { if (!isValidThreshold(threshold)) return; std::lock_guard lock(mLock); - mMap.emplace(uid, threshold); + mMap.emplace(appId, threshold); } -std::optional SmallAreaDetectionAllowMappings::getThresholdForUid(uid_t uid) { +std::optional SmallAreaDetectionAllowMappings::getThresholdForAppId(int32_t appId) { std::lock_guard lock(mLock); - const auto iter = mMap.find(uid); + const auto iter = mMap.find(appId); if (iter != mMap.end()) { return iter->second; } diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h index cbab69091f..e10301c1e8 100644 --- a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h +++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h @@ -24,16 +24,16 @@ namespace android::scheduler { class SmallAreaDetectionAllowMappings { - using UidThresholdMap = std::unordered_map; + using AppIdThresholdMap = std::unordered_map; public: - void update(std::vector>& uidThresholdMappings); - void setThesholdForUid(uid_t uid, float threshold) EXCLUDES(mLock); - std::optional getThresholdForUid(uid_t uid) EXCLUDES(mLock); + void update(std::vector>& appIdThresholdMappings); + void setThesholdForAppId(int32_t appId, float threshold) EXCLUDES(mLock); + std::optional getThresholdForAppId(int32_t uid) EXCLUDES(mLock); private: static bool isValidThreshold(float threshold) { return threshold >= 0.0f && threshold <= 1.0f; } mutable std::mutex mLock; - UidThresholdMap mMap GUARDED_BY(mLock); + AppIdThresholdMap mMap GUARDED_BY(mLock); }; } // namespace android::scheduler diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 38dc435357..ec3050c375 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -8157,13 +8157,13 @@ status_t SurfaceFlinger::setOverrideFrameRate(uid_t uid, float frameRate) { } status_t SurfaceFlinger::updateSmallAreaDetection( - std::vector>& uidThresholdMappings) { - mScheduler->updateSmallAreaDetection(uidThresholdMappings); + std::vector>& appIdThresholdMappings) { + mScheduler->updateSmallAreaDetection(appIdThresholdMappings); return NO_ERROR; } -status_t SurfaceFlinger::setSmallAreaDetectionThreshold(uid_t uid, float threshold) { - mScheduler->setSmallAreaDetectionThreshold(uid, threshold); +status_t SurfaceFlinger::setSmallAreaDetectionThreshold(int32_t appId, float threshold) { + mScheduler->setSmallAreaDetectionThreshold(appId, threshold); return NO_ERROR; } @@ -9530,18 +9530,18 @@ binder::Status SurfaceComposerAIDL::scheduleCommit() { return binder::Status::ok(); } -binder::Status SurfaceComposerAIDL::updateSmallAreaDetection(const std::vector& uids, +binder::Status SurfaceComposerAIDL::updateSmallAreaDetection(const std::vector& appIds, const std::vector& thresholds) { status_t status; const int c_uid = IPCThreadState::self()->getCallingUid(); if (c_uid == AID_ROOT || c_uid == AID_SYSTEM) { - if (uids.size() != thresholds.size()) return binderStatusFromStatusT(BAD_VALUE); + if (appIds.size() != thresholds.size()) return binderStatusFromStatusT(BAD_VALUE); - std::vector> mappings; - const size_t size = uids.size(); + std::vector> mappings; + const size_t size = appIds.size(); mappings.reserve(size); for (int i = 0; i < size; i++) { - auto row = std::make_pair(static_cast(uids[i]), thresholds[i]); + auto row = std::make_pair(appIds[i], thresholds[i]); mappings.push_back(row); } status = mFlinger->updateSmallAreaDetection(mappings); @@ -9552,11 +9552,11 @@ binder::Status SurfaceComposerAIDL::updateSmallAreaDetection(const std::vectorgetCallingUid(); if (c_uid == AID_ROOT || c_uid == AID_SYSTEM) { - status = mFlinger->setSmallAreaDetectionThreshold(uid, threshold); + status = mFlinger->setSmallAreaDetectionThreshold(appId, threshold); } else { ALOGE("setSmallAreaDetectionThreshold() permission denied for uid: %d", c_uid); status = PERMISSION_DENIED; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index dc4e7cf2fe..550319576b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -606,9 +606,9 @@ private: status_t setOverrideFrameRate(uid_t uid, float frameRate); - status_t updateSmallAreaDetection(std::vector>& uidThresholdMappings); + status_t updateSmallAreaDetection(std::vector>& uidThresholdMappings); - status_t setSmallAreaDetectionThreshold(uid_t uid, float threshold); + status_t setSmallAreaDetectionThreshold(int32_t appId, float threshold); int getGpuContextPriority(); @@ -1560,9 +1560,9 @@ public: binder::Status setDebugFlash(int delay) override; binder::Status scheduleComposite() override; binder::Status scheduleCommit() override; - binder::Status updateSmallAreaDetection(const std::vector& uids, + binder::Status updateSmallAreaDetection(const std::vector& appIds, const std::vector& thresholds) override; - binder::Status setSmallAreaDetectionThreshold(int32_t uid, float threshold) override; + binder::Status setSmallAreaDetectionThreshold(int32_t appId, float threshold) override; binder::Status getGpuContextPriority(int32_t* outPriority) override; binder::Status getMaxAcquiredBufferCount(int32_t* buffers) override; binder::Status addWindowInfosListener(const sp& windowInfosListener, diff --git a/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp b/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp index b910485c06..05f9eed30b 100644 --- a/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp +++ b/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp @@ -23,38 +23,34 @@ namespace android::scheduler { -class SmallAreaDetectionMappingsAllowTest : public testing::Test { +class SmallAreaDetectionAllowMappingsTest : public testing::Test { protected: SmallAreaDetectionAllowMappings mMappings; + static constexpr int32_t kAppId1 = 10100; + static constexpr int32_t kAppId2 = 10101; + static constexpr float kThreshold1 = 0.05f; + static constexpr float kThreshold2 = 0.07f; }; namespace { -TEST_F(SmallAreaDetectionMappingsAllowTest, testUpdate) { - const uid_t uid1 = 10100; - const uid_t uid2 = 10101; - const float threshold1 = 0.05f; - const float threshold2 = 0.07f; - std::vector> mappings; +TEST_F(SmallAreaDetectionAllowMappingsTest, testUpdate) { + std::vector> mappings; mappings.reserve(2); - mappings.push_back(std::make_pair(uid1, threshold1)); - mappings.push_back(std::make_pair(uid2, threshold2)); + mappings.push_back(std::make_pair(kAppId1, kThreshold1)); + mappings.push_back(std::make_pair(kAppId2, kThreshold2)); mMappings.update(mappings); - ASSERT_EQ(mMappings.getThresholdForUid(uid1).value(), threshold1); - ASSERT_EQ(mMappings.getThresholdForUid(uid2).value(), threshold2); + ASSERT_EQ(mMappings.getThresholdForAppId(kAppId1).value(), kThreshold1); + ASSERT_EQ(mMappings.getThresholdForAppId(kAppId2).value(), kThreshold2); } -TEST_F(SmallAreaDetectionMappingsAllowTest, testSetThesholdForUid) { - const uid_t uid = 10111; - const float threshold = 0.05f; - - mMappings.setThesholdForUid(uid, threshold); - ASSERT_EQ(mMappings.getThresholdForUid(uid), threshold); +TEST_F(SmallAreaDetectionAllowMappingsTest, testSetThesholdForAppId) { + mMappings.setThesholdForAppId(kAppId1, kThreshold1); + ASSERT_EQ(mMappings.getThresholdForAppId(kAppId1), kThreshold1); } -TEST_F(SmallAreaDetectionMappingsAllowTest, testUidNotInTheMappings) { - const uid_t uid = 10222; - ASSERT_EQ(mMappings.getThresholdForUid(uid), std::nullopt); +TEST_F(SmallAreaDetectionAllowMappingsTest, testAppIdNotInTheMappings) { + ASSERT_EQ(mMappings.getThresholdForAppId(kAppId1), std::nullopt); } } // namespace -- cgit v1.2.3-59-g8ed1b From 316b7f443541f6220ef6b51d8fa5d63ec72736f0 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 13 Oct 2023 23:44:46 +0000 Subject: Fix mPreviouslyPresentedLayerStacks leak for bufferless layers Fix: 295344852 Test: presubmit Change-Id: Ib906c9002c56b8a7398cfcc2ede4a07be7484ce0 --- services/surfaceflinger/Layer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0c1c014640..da87e8e0fc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2941,7 +2941,9 @@ void Layer::onLayerDisplayed(ftl::SharedFuture futureFenceResult, ch->previousReleaseFences.emplace_back(std::move(futureFenceResult)); ch->name = mName; } - mPreviouslyPresentedLayerStacks.push_back(layerStack); + if (mBufferInfo.mBuffer) { + mPreviouslyPresentedLayerStacks.push_back(layerStack); + } } void Layer::onSurfaceFrameCreated( -- cgit v1.2.3-59-g8ed1b From ac7bcd98bd331eca678ffc21188dd78c63aabbdd Mon Sep 17 00:00:00 2001 From: Pascal Muetschard Date: Tue, 3 Oct 2023 15:05:36 +0200 Subject: Include the frame's expected duration in the jank data. Bug: b/261839034 Test: atest libsurfaceflinger_unittest Change-Id: I65c85be8825e36671612a47000261c04f0289551 --- libs/gui/ITransactionCompletedListener.cpp | 2 + .../include/gui/ITransactionCompletedListener.h | 7 +- .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 20 ++- .../surfaceflinger/FrameTimeline/FrameTimeline.h | 18 +- services/surfaceflinger/Layer.cpp | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 +- .../tests/unittests/FrameTimelineTest.cpp | 186 +++++++++++++-------- .../unittests/TransactionSurfaceFrameTest.cpp | 6 +- .../tests/unittests/mock/MockFrameTimeline.h | 2 +- 9 files changed, 158 insertions(+), 91 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index ffe79a3a03..29d64afb24 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -111,12 +111,14 @@ JankData::JankData() status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); SAFE_PARCEL(output->writeInt32, jankType); + SAFE_PARCEL(output->writeInt64, frameIntervalNs); return NO_ERROR; } status_t JankData::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readInt64, &frameVsyncId); SAFE_PARCEL(input->readInt32, &jankType); + SAFE_PARCEL(input->readInt64, &frameIntervalNs); return NO_ERROR; } diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 39bcb4a56c..364a57b8dd 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -120,14 +120,17 @@ public: status_t readFromParcel(const Parcel* input) override; JankData(); - JankData(int64_t frameVsyncId, int32_t jankType) - : frameVsyncId(frameVsyncId), jankType(jankType) {} + JankData(int64_t frameVsyncId, int32_t jankType, nsecs_t frameIntervalNs) + : frameVsyncId(frameVsyncId), jankType(jankType), frameIntervalNs(frameIntervalNs) {} // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId int64_t frameVsyncId; // Bitmask of janks that occurred int32_t jankType; + + // Expected duration of the frame + nsecs_t frameIntervalNs; }; class SurfaceStats : public Parcelable { diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index dcc29b9913..1b1307b13a 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -366,6 +366,11 @@ void SurfaceFrame::setRenderRate(Fps renderRate) { mRenderRate = renderRate; } +Fps SurfaceFrame::getRenderRate() const { + std::lock_guard lock(mMutex); + return mRenderRate ? *mRenderRate : mDisplayFrameRenderRate; +} + void SurfaceFrame::setGpuComposition() { std::scoped_lock lock(mMutex); mGpuComposition = true; @@ -611,9 +616,11 @@ void SurfaceFrame::classifyJankLocked(int32_t displayFrameJankType, const Fps& r } void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate, - nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta) { + Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta, + nsecs_t displayPresentDelta) { std::scoped_lock lock(mMutex); + mDisplayFrameRenderRate = displayFrameRenderRate; mActuals.presentTime = presentTime; nsecs_t deadlineDelta = 0; @@ -837,10 +844,11 @@ void FrameTimeline::addSurfaceFrame(std::shared_ptr surfaceFrame) mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame); } -void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate) { +void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate, + Fps renderRate) { ATRACE_CALL(); std::scoped_lock lock(mMutex); - mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, + mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate, mTokenManager.getPredictionsForToken(token), wakeUpTime); } @@ -860,11 +868,12 @@ void FrameTimeline::DisplayFrame::addSurfaceFrame(std::shared_ptr mSurfaceFrames.push_back(surfaceFrame); } -void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, +void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate, std::optional predictions, nsecs_t wakeUpTime) { mToken = token; mRefreshRate = refreshRate; + mRenderRate = renderRate; if (!predictions) { mPredictionState = PredictionState::Expired; } else { @@ -1026,7 +1035,8 @@ void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previous classifyJank(deadlineDelta, deltaToVsync, previousPresentTime); for (auto& surfaceFrame : mSurfaceFrames) { - surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, deadlineDelta, deltaToVsync); + surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, mRenderRate, deadlineDelta, + deltaToVsync); } } diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index d54d22d53b..538ea1288b 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -183,6 +183,8 @@ public: void setDropTime(nsecs_t dropTime); void setPresentState(PresentState presentState, nsecs_t lastLatchTime = 0); void setRenderRate(Fps renderRate); + // Return the render rate if it exists, otherwise returns the DisplayFrame's render rate. + Fps getRenderRate() const; void setGpuComposition(); // When a bufferless SurfaceFrame is promoted to a buffer SurfaceFrame, we also have to update @@ -197,7 +199,8 @@ public: // displayRefreshRate, displayDeadlineDelta, and displayPresentDelta are propagated from the // display frame. void onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate, - nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta); + Fps displayFrameRenderRate, nsecs_t displayDeadlineDelta, + nsecs_t displayPresentDelta); // All the timestamps are dumped relative to the baseTime void dump(std::string& result, const std::string& indent, nsecs_t baseTime) const; // Dumps only the layer, token, is buffer, jank metadata, prediction and present states. @@ -251,6 +254,8 @@ private: int32_t mJankType GUARDED_BY(mMutex) = JankType::None; // Indicates if this frame was composited by the GPU or not bool mGpuComposition GUARDED_BY(mMutex) = false; + // Refresh rate for this frame. + Fps mDisplayFrameRenderRate GUARDED_BY(mMutex); // Rendering rate for this frame. std::optional mRenderRate GUARDED_BY(mMutex); // Enum for the type of present @@ -298,7 +303,8 @@ public: // The first function called by SF for the current DisplayFrame. Fetches SF predictions based on // the token and sets the actualSfWakeTime for the current DisplayFrame. - virtual void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) = 0; + virtual void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate, + Fps renderRate) = 0; // Sets the sfPresentTime and finalizes the current DisplayFrame. Tracks the // given present fence until it's signaled, and updates the present timestamps of all presented @@ -374,8 +380,8 @@ public: // and SYSTEM_TIME_MONOTONIC. void trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const; // Sets the token, vsyncPeriod, predictions and SF start time. - void onSfWakeUp(int64_t token, Fps refreshRate, std::optional predictions, - nsecs_t wakeUpTime); + void onSfWakeUp(int64_t token, Fps refreshRate, Fps renderRate, + std::optional predictions, nsecs_t wakeUpTime); // Sets the appropriate metadata and classifies the jank. void onPresent(nsecs_t signalTime, nsecs_t previousPresentTime); // Adds the provided SurfaceFrame to the current display frame. @@ -437,6 +443,8 @@ public: // The refresh rate (vsync period) in nanoseconds as seen by SF during this DisplayFrame's // timeline Fps mRefreshRate; + // The current render rate for this DisplayFrame. + Fps mRenderRate; // TraceCookieCounter is used to obtain the cookie for sendig trace packets to perfetto. // Using a reference here because the counter is owned by FrameTimeline, which outlives // DisplayFrame. @@ -453,7 +461,7 @@ public: int32_t layerId, std::string layerName, std::string debugName, bool isBuffer, GameMode) override; void addSurfaceFrame(std::shared_ptr surfaceFrame) override; - void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) override; + void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate, Fps renderRate) override; void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr& presentFence, const std::shared_ptr& gpuFence = FenceTime::NO_FENCE) override; void parseArgs(const Vector& args, std::string& result) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a73c5115b1..5f90a7f82d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -787,8 +787,9 @@ void Layer::transferAvailableJankData(const std::deque>& hand if (includeJankData) { std::shared_ptr surfaceFrame = mPendingJankClassifications.front(); - jankData.emplace_back( - JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value())); + jankData.emplace_back(JankData(surfaceFrame->getToken(), + surfaceFrame->getJankType().value(), + surfaceFrame->getRenderRate().getPeriodNsecs())); } mPendingJankClassifications.pop_front(); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b7d2f9a053..2583868c6e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2487,7 +2487,8 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, { mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId), pacesetterFrameTarget.frameBeginTime().ns(), - Fps::fromPeriodNsecs(vsyncPeriod.ns())); + Fps::fromPeriodNsecs(vsyncPeriod.ns()), + mScheduler->getPacesetterRefreshRate()); const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded); bool transactionsAreEmpty; diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 8911430790..636d852651 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -54,6 +54,8 @@ constexpr int32_t sInputEventId = 5; constexpr int32_t sLayerIdOne = 1; constexpr int32_t sLayerIdTwo = 2; constexpr GameMode sGameMode = GameMode::Unsupported; +constexpr Fps RR_11 = Fps::fromPeriodNsecs(11); +constexpr Fps RR_30 = Fps::fromPeriodNsecs(30); class FrameTimelineTest : public testing::Test { public: @@ -276,7 +278,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { /*isBuffer*/ true, sGameMode); // Set up the display frame - mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(token1, 20, RR_11, RR_11); surfaceFrame1->setDropTime(12); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -309,7 +311,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdTwo, sLayerNameTwo, sLayerNameTwo, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -354,7 +356,7 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, RR_11, RR_11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence); @@ -379,7 +381,7 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, RR_11, RR_11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence); @@ -422,7 +424,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); - mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken, 22, RR_11, RR_11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); mFrameTimeline->setSfPresent(27, presentFence); @@ -439,7 +441,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); - mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken, 22, RR_11, RR_11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); mFrameTimeline->setSfPresent(27, presentFence); @@ -456,7 +458,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); - mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken, 22, RR_11, RR_11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); mFrameTimeline->setSfPresent(27, presentFence); @@ -465,7 +467,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { } TEST_F(FrameTimelineTest, presentFenceSignaled_invalidSignalTime) { - Fps refreshRate = Fps::fromPeriodNsecs(11); + Fps refreshRate = RR_11; auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60}); @@ -478,7 +480,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_invalidSignalTime) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setAcquireFenceTime(20); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -496,7 +498,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_invalidSignalTime) { // Tests related to TimeStats TEST_F(FrameTimelineTest, presentFenceSignaled_doesNotReportForInvalidTokens) { - Fps refreshRate = Fps::fromPeriodNsecs(11); + Fps refreshRate = RR_11; EXPECT_CALL(*mTimeStats, incrementJankyFrames(_)).Times(0); auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); int64_t surfaceFrameToken1 = -1; @@ -509,7 +511,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_doesNotReportForInvalidTokens) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setAcquireFenceTime(20); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -519,7 +521,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_doesNotReportForInvalidTokens) { } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { - Fps refreshRate = Fps::fromPeriodNsecs(11); + Fps refreshRate = RR_11; EXPECT_CALL(*mTimeStats, incrementJankyFrames( TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne, @@ -537,7 +539,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setAcquireFenceTime(20); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -547,7 +549,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfGpu) { - Fps refreshRate = Fps::fromPeriodNsecs(11); + Fps refreshRate = RR_11; EXPECT_CALL(*mTimeStats, incrementJankyFrames( TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne, @@ -566,7 +568,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfGpu) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setAcquireFenceTime(20); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -577,7 +579,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfGpu) { } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { - Fps refreshRate = Fps::fromPeriodNsecs(30); + Fps refreshRate = RR_30; EXPECT_CALL(*mTimeStats, incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne, sLayerNameOne, sGameMode, @@ -594,7 +596,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); surfaceFrame1->setAcquireFenceTime(20); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -622,7 +624,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(45); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -651,7 +653,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(50); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -680,7 +682,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(40); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -709,7 +711,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(40); - mFrameTimeline->setSfWakeUp(sfToken1, 82, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 82, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented, /*previousLatchTime*/ 56); @@ -721,8 +723,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { - Fps refreshRate = Fps::fromPeriodNsecs(11); - Fps renderRate = Fps::fromPeriodNsecs(30); + Fps refreshRate = RR_11; + Fps renderRate = RR_30; EXPECT_CALL(*mTimeStats, incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, renderRate, sUidOne, sLayerNameOne, sGameMode, @@ -740,7 +742,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(45); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); surfaceFrame1->setRenderRate(renderRate); @@ -752,8 +754,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { } TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPresentsSurfaceFrame) { - Fps refreshRate = Fps::fromPeriodNsecs(11); - Fps renderRate = Fps::fromPeriodNsecs(30); + Fps refreshRate = RR_11; + Fps renderRate = RR_30; EXPECT_CALL(*mTimeStats, incrementJankyFrames( @@ -775,7 +777,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPres surfaceFrame1->setAcquireFenceTime(45); // Trigger a prediction expiry flushTokens(); - mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate); + mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate, refreshRate); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); surfaceFrame1->setRenderRate(renderRate); @@ -814,7 +816,7 @@ TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) { /*isBuffer*/ true, sGameMode); // Set up the display frame - mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(token1, 20, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(25, presentFence1); @@ -844,7 +846,7 @@ TEST_F(FrameTimelineTest, tracing_sanityTest) { /*isBuffer*/ true, sGameMode); // Set up the display frame - mFrameTimeline->setSfWakeUp(token2, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(token2, 20, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(25, presentFence1); @@ -866,7 +868,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) tracingSession->StartBlocking(); // Set up the display frame - mFrameTimeline->setSfWakeUp(-1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(-1, 20, RR_11, RR_11); mFrameTimeline->setSfPresent(25, presentFence1); presentFence1->signalForTest(30); @@ -890,7 +892,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) /*isBuffer*/ true, sGameMode); // Set up the display frame - mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(token1, 20, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(25, presentFence1); @@ -1068,7 +1070,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { int64_t displayFrameToken1 = mTokenManager->generateTokenForPredictions({10, 30, 30}); // Set up the display frame - mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, RR_11, RR_11); mFrameTimeline->setSfPresent(26, presentFence1); presentFence1->signalForTest(31); @@ -1150,7 +1152,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_predictionExpiredDoesNotTraceExpecte addEmptySurfaceFrame(); // Set up the display frame - mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, RR_11, RR_11); mFrameTimeline->setSfPresent(26, presentFence1); presentFence1->signalForTest(31); @@ -1252,7 +1254,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { auto protoPresentedSurfaceFrameActualEnd = createProtoFrameEnd(traceCookie + 4); // Set up the display frame - mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -1398,7 +1400,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredIsAppMissedDeadline auto protoActualSurfaceFrameEnd = createProtoFrameEnd(traceCookie + 1); // Set up the display frame - mFrameTimeline->setSfWakeUp(displayFrameToken, sfStartTime, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(displayFrameToken, sfStartTime, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(sfEndTime, presentFence1); @@ -1475,7 +1477,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDroppedFramesTraced auto protoActualSurfaceFrameEnd = createProtoFrameEnd(traceCookie + 1); // Set up the display frame - mFrameTimeline->setSfWakeUp(displayFrameToken, sfStartTime, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(displayFrameToken, sfStartTime, RR_11, RR_11); surfaceFrame1->setDropTime(sfStartTime); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -1528,7 +1530,7 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); - mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); mFrameTimeline->setSfPresent(26, presentFence1); @@ -1552,11 +1554,11 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { } TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresent) { - Fps vsyncRate = Fps::fromPeriodNsecs(11); + Fps vsyncRate = RR_11; auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 30, 40}); int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 70}); - mFrameTimeline->setSfWakeUp(sfToken1, 22, vsyncRate); + mFrameTimeline->setSfWakeUp(sfToken1, 22, vsyncRate, vsyncRate); mFrameTimeline->setSfPresent(26, presentFence1); auto displayFrame = getDisplayFrame(0); presentFence1->signalForTest(30); @@ -1566,7 +1568,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresen // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTimeline->setSfWakeUp(sfToken2, 52, vsyncRate); + mFrameTimeline->setSfWakeUp(sfToken2, 52, vsyncRate, vsyncRate); mFrameTimeline->setSfPresent(56, presentFence2); displayFrame = getDisplayFrame(0); @@ -1591,11 +1593,11 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresen } TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent) { - Fps vsyncRate = Fps::fromPeriodNsecs(11); + Fps vsyncRate = RR_11; auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 30, 40}); int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 70}); - mFrameTimeline->setSfWakeUp(sfToken1, 22, vsyncRate); + mFrameTimeline->setSfWakeUp(sfToken1, 22, vsyncRate, vsyncRate); mFrameTimeline->setSfPresent(26, presentFence1); auto displayFrame = getDisplayFrame(0); presentFence1->signalForTest(50); @@ -1605,7 +1607,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTimeline->setSfWakeUp(sfToken2, 52, vsyncRate); + mFrameTimeline->setSfWakeUp(sfToken2, 52, vsyncRate, vsyncRate); mFrameTimeline->setSfPresent(56, presentFence2); displayFrame = getDisplayFrame(0); @@ -1633,7 +1635,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishEarlyPresent) { auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); int64_t sfToken1 = mTokenManager->generateTokenForPredictions({12, 18, 40}); - mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 12, RR_11, RR_11); mFrameTimeline->setSfPresent(22, presentFence1); auto displayFrame = getDisplayFrame(0); @@ -1673,7 +1675,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) int64_t sfToken4 = mTokenManager->generateTokenForPredictions({112, 120, 120}); // case 1 - cpu time = 33 - 12 = 21, vsync period = 11 - mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 12, RR_11, RR_11); mFrameTimeline->setSfPresent(33, presentFence1, gpuFence1); auto displayFrame0 = getDisplayFrame(0); gpuFence1->signalForTest(36); @@ -1683,7 +1685,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame0->getActuals().presentTime, 0); // case 2 - cpu time = 56 - 52 = 4, vsync period = 30 - mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken2, 52, RR_30, RR_30); mFrameTimeline->setSfPresent(56, presentFence2, gpuFence2); auto displayFrame1 = getDisplayFrame(1); gpuFence2->signalForTest(76); @@ -1697,7 +1699,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame0->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); // case 3 - cpu time = 86 - 82 = 4, vsync period = 30 - mFrameTimeline->setSfWakeUp(sfToken3, 106, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken3, 106, RR_30, RR_30); mFrameTimeline->setSfPresent(112, presentFence3, gpuFence3); auto displayFrame2 = getDisplayFrame(2); gpuFence3->signalForTest(116); @@ -1711,7 +1713,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) EXPECT_EQ(displayFrame1->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); // case 4 - cpu time = 86 - 82 = 4, vsync period = 30 - mFrameTimeline->setSfWakeUp(sfToken4, 120, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken4, 120, RR_30, RR_30); mFrameTimeline->setSfPresent(140, presentFence4, gpuFence4); auto displayFrame3 = getDisplayFrame(3); gpuFence4->signalForTest(156); @@ -1748,7 +1750,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(16); - mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(27, presentFence1); @@ -1771,7 +1773,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame2->setAcquireFenceTime(36); - mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken2, 52, RR_11, RR_11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame2); mFrameTimeline->setSfPresent(57, presentFence2); @@ -1799,10 +1801,10 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen ::testing::Mock::VerifyAndClearExpectations(mTimeStats.get()); EXPECT_CALL(*mTimeStats, - incrementJankyFrames( - TimeStats::JankyFramesInfo{Fps::fromPeriodNsecs(11), std::nullopt, sUidOne, - sLayerNameOne, sGameMode, - JankType::PredictionError, -3, 5, 0})); + incrementJankyFrames(TimeStats::JankyFramesInfo{RR_11, std::nullopt, sUidOne, + sLayerNameOne, sGameMode, + JankType::PredictionError, -3, 5, + 0})); addEmptyDisplayFrame(); @@ -1834,7 +1836,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(16); - mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(26, presentFence1); @@ -1857,7 +1859,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame2->setAcquireFenceTime(36); - mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken2, 52, RR_11, RR_11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame2); mFrameTimeline->setSfPresent(57, presentFence2); @@ -1885,10 +1887,10 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent ::testing::Mock::VerifyAndClearExpectations(mTimeStats.get()); EXPECT_CALL(*mTimeStats, - incrementJankyFrames( - TimeStats::JankyFramesInfo{Fps::fromPeriodNsecs(11), std::nullopt, sUidOne, - sLayerNameOne, sGameMode, - JankType::PredictionError, -3, 5, 0})); + incrementJankyFrames(TimeStats::JankyFramesInfo{RR_11, std::nullopt, sUidOne, + sLayerNameOne, sGameMode, + JankType::PredictionError, -3, 5, + 0})); addEmptyDisplayFrame(); @@ -1919,7 +1921,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(40); - mFrameTimeline->setSfWakeUp(sfToken1, 42, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 42, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(46, presentFence1); @@ -1966,7 +1968,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(26); - mFrameTimeline->setSfWakeUp(sfToken1, 32, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 32, RR_11, RR_11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(36, presentFence1); @@ -1989,7 +1991,7 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame2->setAcquireFenceTime(40); - mFrameTimeline->setSfWakeUp(sfToken2, 43, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken2, 43, RR_11, RR_11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame2); mFrameTimeline->setSfPresent(56, presentFence2); @@ -2047,7 +2049,7 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(50); - mFrameTimeline->setSfWakeUp(sfToken1, 52, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken1, 52, RR_30, RR_30); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(56, presentFence1); @@ -2070,7 +2072,7 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame2->setAcquireFenceTime(84); - mFrameTimeline->setSfWakeUp(sfToken2, 112, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken2, 112, RR_30, RR_30); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54); mFrameTimeline->addSurfaceFrame(surfaceFrame2); mFrameTimeline->setSfPresent(116, presentFence2); @@ -2131,7 +2133,7 @@ TEST_F(FrameTimelineTest, jankClassification_appDeadlineAdjustedForBufferStuffin sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame1->setAcquireFenceTime(50); - mFrameTimeline->setSfWakeUp(sfToken1, 52, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken1, 52, RR_30, RR_30); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); mFrameTimeline->setSfPresent(56, presentFence1); @@ -2154,7 +2156,7 @@ TEST_F(FrameTimelineTest, jankClassification_appDeadlineAdjustedForBufferStuffin sLayerNameOne, sLayerNameOne, /*isBuffer*/ true, sGameMode); surfaceFrame2->setAcquireFenceTime(80); - mFrameTimeline->setSfWakeUp(sfToken2, 82, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken2, 82, RR_30, RR_30); // Setting previous latch time to 54, adjusted deadline will be 54 + vsyncTime(30) = 84 surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54); mFrameTimeline->addSurfaceFrame(surfaceFrame2); @@ -2206,7 +2208,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_G int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 60}); // Case 1: cpu time = 33 - 12 = 21, vsync period = 11 - mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 12, RR_11, RR_11); mFrameTimeline->setSfPresent(33, presentFence1, gpuFence1); auto displayFrame = getDisplayFrame(0); gpuFence1->signalForTest(36); @@ -2225,7 +2227,7 @@ TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent_G EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed); // Case 2: No GPU fence so it will not use GPU composition. - mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(30)); + mFrameTimeline->setSfWakeUp(sfToken2, 52, RR_30, RR_30); mFrameTimeline->setSfPresent(66, presentFence2); auto displayFrame2 = getDisplayFrame(2); // 2 because of previous empty frame presentFence2->signalForTest(90); @@ -2250,13 +2252,13 @@ TEST_F(FrameTimelineTest, jankClassification_presentFenceError) { int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 60}); int64_t sfToken3 = mTokenManager->generateTokenForPredictions({72, 80, 80}); - mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken1, 22, RR_11, RR_11); mFrameTimeline->setSfPresent(26, erroneousPresentFence1); - mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken2, 52, RR_11, RR_11); mFrameTimeline->setSfPresent(60, erroneousPresentFence2); - mFrameTimeline->setSfWakeUp(sfToken3, 72, Fps::fromPeriodNsecs(11)); + mFrameTimeline->setSfWakeUp(sfToken3, 72, RR_11, RR_11); mFrameTimeline->setSfPresent(80, validPresentFence); erroneousPresentFence2->signalForTest(2); @@ -2479,4 +2481,44 @@ TEST_F(FrameTimelineTest, getMinTime) { mFrameTimeline->setSfPresent(50, presentFence); ASSERT_EQ(surfaceFrame->getBaseTime(), 50); } + +TEST_F(FrameTimelineTest, surfaceFrameRenderRateUsingDisplayRate) { + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); + FrameTimelineInfo ftInfo; + ftInfo.vsyncId = token1; + ftInfo.inputEventId = sInputEventId; + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne, + /*isBuffer*/ true, sGameMode); + + mFrameTimeline->setSfWakeUp(token1, 20, RR_30, RR_11); + surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame); + presentFence1->signalForTest(std::chrono::nanoseconds(50ns).count()); + mFrameTimeline->setSfPresent(50, presentFence1); + + EXPECT_EQ(surfaceFrame->getRenderRate().getPeriodNsecs(), 11); +} + +TEST_F(FrameTimelineTest, surfaceFrameRenderRateUsingAppFrameRate) { + auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); + FrameTimelineInfo ftInfo; + ftInfo.vsyncId = token1; + ftInfo.inputEventId = sInputEventId; + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne, + sLayerNameOne, sLayerNameOne, + /*isBuffer*/ true, sGameMode); + surfaceFrame->setRenderRate(RR_30); + mFrameTimeline->setSfWakeUp(token1, 20, RR_11, RR_11); + surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame); + presentFence1->signalForTest(std::chrono::nanoseconds(50ns).count()); + mFrameTimeline->setSfPresent(50, presentFence1); + + EXPECT_EQ(surfaceFrame->getRenderRate().getPeriodNsecs(), 30); +} } // namespace android::frametimeline diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index caa265fcd9..5046a86304 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -347,7 +347,7 @@ public: // Both the droppedSurfaceFrame and presentedSurfaceFrame should be in // pendingJankClassifications. EXPECT_EQ(2u, layer->mPendingJankClassifications.size()); - presentedSurfaceFrame->onPresent(20, JankType::None, 90_Hz, + presentedSurfaceFrame->onPresent(20, JankType::None, 90_Hz, 90_Hz, /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); layer->releasePendingBuffer(25); @@ -484,10 +484,10 @@ public: // BufferlessSurfaceFrames are immediately set to presented and added to the DisplayFrame. // Since we don't have access to DisplayFrame here, trigger an onPresent directly. for (auto& surfaceFrame : bufferlessSurfaceFrames) { - surfaceFrame->onPresent(20, JankType::None, 90_Hz, + surfaceFrame->onPresent(20, JankType::None, 90_Hz, 90_Hz, /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); } - presentedBufferSurfaceFrame->onPresent(20, JankType::None, 90_Hz, + presentedBufferSurfaceFrame->onPresent(20, JankType::None, 90_Hz, 90_Hz, /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h index 5dc48c3703..3f2a917ddc 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h @@ -31,7 +31,7 @@ public: MOCK_METHOD0(onBootFinished, void()); MOCK_METHOD1(addSurfaceFrame, void(std::shared_ptr)); - MOCK_METHOD3(setSfWakeUp, void(int64_t, nsecs_t, Fps)); + MOCK_METHOD4(setSfWakeUp, void(int64_t, nsecs_t, Fps, Fps)); MOCK_METHOD3(setSfPresent, void(nsecs_t, const std::shared_ptr&, const std::shared_ptr&)); -- cgit v1.2.3-59-g8ed1b From 0df8c2e698f36da0faf34f5a5491ac9b70af5cf7 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 17 Oct 2023 19:18:38 +0000 Subject: Remove some unused fields from Layer Bug: 295456126 Test: builds Change-Id: Ic8ffd8326eec571883366e6254f3c5e53d06bcc8 --- services/surfaceflinger/Layer.cpp | 5 ----- services/surfaceflinger/Layer.h | 3 --- 2 files changed, 8 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 97326e98c1..28f4720ae2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2931,11 +2931,6 @@ void Layer::onLayerDisplayed(ftl::SharedFuture futureFenceResult, } } - // Prevent tracing the same release multiple times. - if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mPreviousReleasedFrameNumber = mPreviousFrameNumber; - } - if (ch != nullptr) { ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; ch->previousReleaseFences.emplace_back(std::move(futureFenceResult)); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f67da2aee4..26e4666ab1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1235,9 +1235,6 @@ private: ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; sp mPreviousReleaseBufferEndpoint; - uint64_t mPreviousReleasedFrameNumber = 0; - - uint64_t mPreviousBarrierFrameNumber = 0; bool mReleasePreviousBuffer = false; -- cgit v1.2.3-59-g8ed1b From 69f9522d248a61a25d2ca6435c835a68a40fcba2 Mon Sep 17 00:00:00 2001 From: Arthur Hung Date: Wed, 4 Oct 2023 07:39:02 +0000 Subject: Change small area detection to support new front end design This will still use legacy layer to calculate the small dirty, and update the info to the LayerSnapshot. Also fix some issues in setIsSmallDirty() for 1. Set mSmallDirty flag as false if the surface damage region is invalid. 2. Apply the scaling to the damage region before dirty area calculations. Bug: 295062543 Bug: 303258910 Bug: 303609027 Test: atest LayerHistoryTest Test: atest SmallAreaDetectionTest Change-Id: Ib0e3737e63b5653422b5b5054b893578dc63f768 --- services/surfaceflinger/FrontEnd/LayerSnapshot.h | 2 + services/surfaceflinger/Layer.cpp | 17 +++- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 39 +++++---- .../tests/unittests/LayerHierarchyTest.h | 24 ++++++ .../unittests/LayerHistoryIntegrationTest.cpp | 98 ++++++++++++++++++++++ .../tests/unittests/TestableScheduler.h | 5 +- .../tests/unittests/TestableSurfaceFlinger.h | 5 ++ 8 files changed, 173 insertions(+), 20 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index 80a51ea94c..1b6fdae8aa 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -122,6 +122,8 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { ReachableByRelativeParent }; Reachablilty reachablilty; + // True when the surfaceDamage is recognized as a small area update. + bool isSmallDirty = false; static bool isOpaqueFormat(PixelFormat format); static bool isTransformValid(const ui::Transform& t); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 73b1ca825f..f75f9f6d68 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3369,7 +3369,7 @@ bool Layer::setSurfaceDamageRegion(const Region& surfaceDamage) { mDrawingState.surfaceDamageRegion = surfaceDamage; mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); - setIsSmallDirty(); + setIsSmallDirty(surfaceDamage, getTransform()); return true; } @@ -4416,7 +4416,9 @@ void Layer::updateLastLatchTime(nsecs_t latchTime) { mLastLatchTime = latchTime; } -void Layer::setIsSmallDirty() { +void Layer::setIsSmallDirty(const Region& damageRegion, + const ui::Transform& layerToDisplayTransform) { + mSmallDirty = false; if (!mFlinger->mScheduler->supportSmallDirtyDetection()) { return; } @@ -4425,17 +4427,26 @@ void Layer::setIsSmallDirty() { mWindowType != WindowInfo::Type::BASE_APPLICATION) { return; } - Rect bounds = mDrawingState.surfaceDamageRegion.getBounds(); + + Rect bounds = damageRegion.getBounds(); if (!bounds.isValid()) { return; } + // Transform to screen space. + bounds = layerToDisplayTransform.transform(bounds); + // If the damage region is a small dirty, this could give the hint for the layer history that // it could suppress the heuristic rate when calculating. mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerAppId, bounds.getWidth() * bounds.getHeight()); } +void Layer::setIsSmallDirty(frontend::LayerSnapshot* snapshot) { + setIsSmallDirty(snapshot->surfaceDamage, snapshot->localTransform); + snapshot->isSmallDirty = mSmallDirty; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f67da2aee4..c042395a6d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -937,7 +937,8 @@ public: const sp mFlinger; // Check if the damage region is a small dirty. - void setIsSmallDirty(); + void setIsSmallDirty(const Region& damageRegion, const ui::Transform& layerToDisplayTransform); + void setIsSmallDirty(frontend::LayerSnapshot* snapshot); protected: // For unit tests diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b13c0e8c1f..181a9bfc36 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2211,8 +2211,29 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) { continue; } - if (!snapshot->changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) && - (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) == 0) { + const bool updateSmallDirty = mScheduler->supportSmallDirtyDetection() && + ((snapshot->clientChanges & layer_state_t::eSurfaceDamageRegionChanged) || + snapshot->changes.any(Changes::Geometry)); + + const bool hasChanges = + snapshot->changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) || + (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) != + 0; + + if (!updateSmallDirty && !hasChanges) { + continue; + } + + auto it = mLegacyLayers.find(snapshot->sequence); + LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldn't find layer object for %s", + snapshot->getDebugString().c_str()); + + if (updateSmallDirty) { + // Update small dirty flag while surface damage region or geometry changed + it->second->setIsSmallDirty(snapshot.get()); + } + + if (!hasChanges) { continue; } @@ -2222,12 +2243,9 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) { .transform = snapshot->geomLayerTransform, .setFrameRateVote = snapshot->frameRate, .frameRateSelectionPriority = snapshot->frameRateSelectionPriority, + .isSmallDirty = snapshot->isSmallDirty, }; - auto it = mLegacyLayers.find(snapshot->sequence); - LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s", - snapshot->getDebugString().c_str()); - if (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) { mScheduler->setDefaultFrameRateCompatibility(snapshot->sequence, snapshot->defaultFrameRateCompatibility); @@ -8492,15 +8510,6 @@ void SurfaceFlinger::sample() { void SurfaceFlinger::onActiveDisplaySizeChanged(const DisplayDevice& activeDisplay) { mScheduler->onActiveDisplayAreaChanged(activeDisplay.getWidth() * activeDisplay.getHeight()); getRenderEngine().onActiveDisplaySizeChanged(activeDisplay.getSize()); - - // Notify layers to update small dirty flag. - if (mScheduler->supportSmallDirtyDetection()) { - mCurrentState.traverse([&](Layer* layer) { - if (layer->getLayerStack() == activeDisplay.getLayerStack()) { - layer->setIsSmallDirty(); - } - }); - } } sp SurfaceFlinger::getActivatableDisplay() const { diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h index 7f3171f13f..48f8923415 100644 --- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h +++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h @@ -421,6 +421,17 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setDamageRegion(uint32_t id, const Region& damageRegion) { + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = layer_state_t::eSurfaceDamageRegionChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.surfaceDamageRegion = damageRegion; + mLifecycleManager.applyTransactions(transactions); + } + void setDataspace(uint32_t id, ui::Dataspace dataspace) { std::vector transactions; transactions.emplace_back(); @@ -432,6 +443,19 @@ protected: mLifecycleManager.applyTransactions(transactions); } + void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) { + layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy}; + + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = layer_state_t::eMatrixChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.matrix = matrix; + mLifecycleManager.applyTransactions(transactions); + } + void setShadowRadius(uint32_t id, float shadowRadius) { std::vector transactions; transactions.emplace_back(); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp index a462082141..631adf11c8 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp @@ -866,6 +866,104 @@ TEST_P(LayerHistoryIntegrationTestParameterized, HeuristicLayerWithInfrequentLay } } +class SmallAreaDetectionTest : public LayerHistoryIntegrationTest { +protected: + static constexpr int32_t DISPLAY_WIDTH = 100; + static constexpr int32_t DISPLAY_HEIGHT = 100; + + static constexpr int32_t kAppId1 = 10100; + static constexpr int32_t kAppId2 = 10101; + + static constexpr float kThreshold1 = 0.05f; + static constexpr float kThreshold2 = 0.07f; + + SmallAreaDetectionTest() : LayerHistoryIntegrationTest() { + std::vector> mappings; + mappings.reserve(2); + mappings.push_back(std::make_pair(kAppId1, kThreshold1)); + mappings.push_back(std::make_pair(kAppId2, kThreshold2)); + + mFlinger.enableNewFrontEnd(); + + mScheduler->onActiveDisplayAreaChanged(DISPLAY_WIDTH * DISPLAY_HEIGHT); + mScheduler->updateSmallAreaDetection(mappings); + } + + auto createLegacyAndFrontedEndLayer(uint32_t sequence) { + std::string layerName = "test layer:" + std::to_string(sequence); + + LayerCreationArgs args = LayerCreationArgs{mFlinger.flinger(), + nullptr, + layerName, + 0, + {}, + std::make_optional(sequence)}; + args.ownerUid = kAppId1; + args.metadata.setInt32(gui::METADATA_WINDOW_TYPE, 2); // APPLICATION + const auto layer = sp::make(args); + mFlinger.injectLegacyLayer(layer); + createRootLayer(sequence); + return layer; + } +}; + +TEST_F(SmallAreaDetectionTest, SmallDirtyLayer) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + uint32_t sequence = static_cast(layer->sequence); + setBuffer(sequence); + setDamageRegion(sequence, Region(Rect(10, 10))); + updateLayerSnapshotsAndLayerHistory(time); + + ASSERT_EQ(true, mFlinger.mutableLayerSnapshotBuilder().getSnapshot(1)->isSmallDirty); +} + +TEST_F(SmallAreaDetectionTest, NotSmallDirtyLayer) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + uint32_t sequence = static_cast(layer->sequence); + setBuffer(sequence); + setDamageRegion(sequence, Region(Rect(50, 50))); + updateLayerSnapshotsAndLayerHistory(time); + + ASSERT_EQ(false, mFlinger.mutableLayerSnapshotBuilder().getSnapshot(1)->isSmallDirty); +} + +TEST_F(SmallAreaDetectionTest, smallDirtyLayerWithMatrix) { + auto layer = createLegacyAndFrontedEndLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // Original damage region is a small dirty. + uint32_t sequence = static_cast(layer->sequence); + setBuffer(sequence); + setDamageRegion(sequence, Region(Rect(20, 20))); + updateLayerSnapshotsAndLayerHistory(time); + ASSERT_EQ(true, mFlinger.mutableLayerSnapshotBuilder().getSnapshot(1)->isSmallDirty); + + setMatrix(sequence, 2.0f, 0, 0, 2.0f); + updateLayerSnapshotsAndLayerHistory(time); + + // Verify if the small dirty is scaled. + ASSERT_EQ(false, mFlinger.mutableLayerSnapshotBuilder().getSnapshot(1)->isSmallDirty); +} + INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryIntegrationTestParameterized, ::testing::Values(1s, 2s, 3s, 4s, 5s)); diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 014d07c38f..3d1c900dcf 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -44,7 +44,10 @@ public: TestableScheduler(std::unique_ptr controller, std::shared_ptr tracker, RefreshRateSelectorPtr selectorPtr, sp modulatorPtr, ISchedulerCallback& callback) - : Scheduler(*this, callback, Feature::kContentDetection, std::move(modulatorPtr)) { + : Scheduler(*this, callback, + (FeatureFlags)Feature::kContentDetection | + Feature::kSmallDirtyContentDetection, + std::move(modulatorPtr)) { const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId(); registerDisplay(displayId, std::move(selectorPtr), std::move(controller), std::move(tracker)); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 3b3942012f..8f1982d6c3 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -670,6 +670,11 @@ public: return mFlinger->initTransactionTraceWriter(); } + void enableNewFrontEnd() { + mFlinger->mLayerLifecycleManagerEnabled = true; + mFlinger->mLegacyFrontEndEnabled = false; + } + ~TestableSurfaceFlinger() { // All these pointer and container clears help ensure that GMock does // not report a leaked object, since the SurfaceFlinger instance may -- cgit v1.2.3-59-g8ed1b From 5b581496043c6a916eabe718dc41aa3c79fcb360 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Tue, 31 Oct 2023 14:29:41 -0400 Subject: SF: Rename postComposition and related for clarity The "post" in "postComposition" (and related "onPostComposition") can be read as a preposition or a verb, making the name less easy to understand. We believe "postComposition" is intended to mean "after composition". More precisely, it is called after calling `present`, so rename to "onCompositionPresented". Rename the related "postComposition" on other classes (Layer, Scheduler) to match. Splitting out from original motivating discussion in Ib9d074671e32c95875ef7e0791dd95d6e595e47a. Bug: 241285491 Bug: 259132483 Test: No new behavior; no new tests Change-Id: I7f62728ea35aee47ebeac10dc7de82258080690e --- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/Layer.cpp | 8 ++++---- services/surfaceflinger/Layer.h | 11 ++++------- services/surfaceflinger/Scheduler/Scheduler.cpp | 2 +- services/surfaceflinger/Scheduler/Scheduler.h | 4 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 15 ++++++++------- services/surfaceflinger/SurfaceFlinger.h | 4 ++-- .../surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h | 4 ++-- .../surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp | 2 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 2 +- 10 files changed, 26 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index e7b1232eac..86ced2ccf2 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -1341,7 +1341,7 @@ protected: newFrame->mRefreshes[0].mGpuCompositionDone.mFenceTime : FenceTime::NO_FENCE; // HWC2 releases the previous buffer after a new latch just before - // calling postComposition. + // calling onCompositionPresented. if (oldFrame != nullptr) { mCfeh->addRelease(nOldFrame, oldFrame->kDequeueReadyTime, std::shared_ptr(oldFrame->mRelease.mFenceTime)); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 700baa22a6..7c3a8c1ae1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -4024,10 +4024,10 @@ bool Layer::isVisible() const { return getAlpha() > 0.0f || hasBlur(); } -void Layer::onPostComposition(const DisplayDevice* display, - const std::shared_ptr& glDoneFence, - const std::shared_ptr& presentFence, - const CompositorTiming& compositorTiming) { +void Layer::onCompositionPresented(const DisplayDevice* display, + const std::shared_ptr& glDoneFence, + const std::shared_ptr& presentFence, + const CompositorTiming& compositorTiming) { // mFrameLatencyNeeded is true when a new frame was latched for the // composition. if (!mBufferInfo.mFrameLatencyNeeded) return; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index dd91adcba7..91cd783fda 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -433,13 +433,10 @@ public: void updateCloneBufferInfo(); uint64_t mPreviousFrameNumber = 0; - /* - * called after composition. - * returns true if the layer latched a new buffer this frame. - */ - void onPostComposition(const DisplayDevice*, const std::shared_ptr& /*glDoneFence*/, - const std::shared_ptr& /*presentFence*/, - const CompositorTiming&); + void onCompositionPresented(const DisplayDevice*, + const std::shared_ptr& /*glDoneFence*/, + const std::shared_ptr& /*presentFence*/, + const CompositorTiming&); // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/); diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 1a8713d4a9..2a07e4d9ea 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -1165,7 +1165,7 @@ void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimel } } -bool Scheduler::onPostComposition(nsecs_t presentTime) { +bool Scheduler::onCompositionPresented(nsecs_t presentTime) { std::lock_guard lock(mVsyncTimelineLock); if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) { if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index b0520a61ff..6eb5125d5a 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -281,8 +281,8 @@ public: // Notifies the scheduler about a refresh rate timeline change. void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); - // Notifies the scheduler post composition. Returns if recomposite is needed. - bool onPostComposition(nsecs_t presentTime); + // Notifies the scheduler once the composition is presented. Returns if recomposite is needed. + bool onCompositionPresented(nsecs_t presentTime); // Notifies the scheduler when the display size has changed. Called from SF's main thread void onActiveDisplayAreaChanged(uint32_t displayArea); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 62eb17d2e7..07d67264f5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2747,11 +2747,11 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( mPowerAdvisor->reportActualWorkDuration(); } - if (mScheduler->onPostComposition(presentTime)) { + if (mScheduler->onCompositionPresented(presentTime)) { scheduleComposite(FrameHint::kNone); } - postComposition(pacesetterId, frameTargeters, presentTime); + onCompositionPresented(pacesetterId, frameTargeters, presentTime); const bool hadGpuComposited = multiDisplayUnion(mCompositionCoverage).test(CompositionCoverage::Gpu); @@ -2908,9 +2908,9 @@ ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId, return ui::ROTATION_0; } -void SurfaceFlinger::postComposition(PhysicalDisplayId pacesetterId, - const scheduler::FrameTargeters& frameTargeters, - nsecs_t presentStartTime) { +void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, + const scheduler::FrameTargeters& frameTargeters, + nsecs_t presentStartTime) { ATRACE_CALL(); ALOGV(__func__); @@ -3004,8 +3004,9 @@ void SurfaceFlinger::postComposition(PhysicalDisplayId pacesetterId, mLayersWithBuffersRemoved.clear(); for (const auto& layer: mLayersWithQueuedFrames) { - layer->onPostComposition(pacesetterDisplay.get(), pacesetterGpuCompositionDoneFenceTime, - pacesetterPresentFenceTime, compositorTiming); + layer->onCompositionPresented(pacesetterDisplay.get(), + pacesetterGpuCompositionDoneFenceTime, + pacesetterPresentFenceTime, compositorTiming); layer->releasePendingBuffer(presentTime.ns()); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 520bd221b3..dd56517791 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -982,8 +982,8 @@ private: /* * Compositing */ - void postComposition(PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters&, - nsecs_t presentStartTime) REQUIRES(kMainThreadContext); + void onCompositionPresented(PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters&, + nsecs_t presentStartTime) REQUIRES(kMainThreadContext); /* * Display management diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index c4077dfbaa..7d49d941ce 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -610,8 +610,8 @@ public: mFlinger->flushTransactionQueues(getFuzzedVsyncId(mFdp)); scheduler::FrameTargeter frameTargeter(displayId, mFdp.ConsumeBool()); - mFlinger->postComposition(displayId, ftl::init::map(displayId, &frameTargeter), - mFdp.ConsumeIntegral()); + mFlinger->onCompositionPresented(displayId, ftl::init::map(displayId, &frameTargeter), + mFdp.ConsumeIntegral()); } mFlinger->setTransactionFlags(mFdp.ConsumeIntegral()); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp index 39a7ee5c12..7aae3c4a1a 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp @@ -133,7 +133,7 @@ void LayerFuzzer::invokeBufferStateLayer() { ui::LayerStack::fromValue(mFdp.ConsumeIntegral())); layer->releasePendingBuffer(mFdp.ConsumeIntegral()); - layer->onPostComposition(nullptr, fenceTime, fenceTime, compositorTiming); + layer->onCompositionPresented(nullptr, fenceTime, fenceTime, compositorTiming); layer->setTransform(mFdp.ConsumeIntegral()); layer->setTransformToDisplayInverse(mFdp.ConsumeBool()); diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index 00b5bf0506..d4d5b32341 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -112,7 +112,7 @@ public: EXPECT_CALL(*mFlinger.getFrameTracer(), traceFence(layerId, bufferId, frameNumber, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE, /*startTime*/ 0)); - layer->onPostComposition(nullptr, glDoneFence, presentFence, compositorTiming); + layer->onCompositionPresented(nullptr, glDoneFence, presentFence, compositorTiming); } }; -- cgit v1.2.3-59-g8ed1b From 89f5d4ebf7ba08e4f655550623fb5d78aa638f28 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 20 Oct 2023 17:12:49 +0000 Subject: Front buffered layers vote for max ...because all known use-cases for beam racing want low latency which implies clocking the display to max Bug: 305997105 Test: libsurfaceflinger_unittest Test: test app with front buffered layers + youtube pip stays at max Change-Id: Ibe33d4b43ea4943874f104409e3bc247f00cae33 --- services/surfaceflinger/FrontEnd/LayerSnapshot.cpp | 8 +++++ services/surfaceflinger/FrontEnd/LayerSnapshot.h | 1 + services/surfaceflinger/Layer.cpp | 8 +++++ services/surfaceflinger/Layer.h | 17 +++++----- services/surfaceflinger/Scheduler/LayerHistory.cpp | 5 +++ services/surfaceflinger/Scheduler/LayerInfo.cpp | 12 +++++++ services/surfaceflinger/Scheduler/LayerInfo.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 2 ++ .../tests/unittests/LayerHistoryTest.cpp | 37 ++++++++++++++++++++++ .../tests/unittests/LayerInfoTest.cpp | 18 +++++++++++ .../tests/unittests/LayerSnapshotTest.cpp | 20 ++++++++++++ .../tests/unittests/mock/MockLayer.h | 1 + 12 files changed, 123 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 7a85da056e..38974a2f58 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -332,6 +332,14 @@ FloatRect LayerSnapshot::sourceBounds() const { return geomBufferSize.toFloatRect(); } +bool LayerSnapshot::isFrontBuffered() const { + if (!externalTexture) { + return false; + } + + return externalTexture->getUsage() & AHARDWAREBUFFER_USAGE_FRONT_BUFFER; +} + Hwc2::IComposerClient::BlendMode LayerSnapshot::getBlendMode( const RequestedLayerState& requested) const { auto blendMode = Hwc2::IComposerClient::BlendMode::NONE; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index 4fd6495422..73ee22fa21 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -143,6 +143,7 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { std::string getIsVisibleReason() const; bool hasInputInfo() const; FloatRect sourceBounds() const; + bool isFrontBuffered() const; Hwc2::IComposerClient::BlendMode getBlendMode(const RequestedLayerState& requested) const; friend std::ostream& operator<<(std::ostream& os, const LayerSnapshot& obj); void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 700baa22a6..98f34cf171 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -4230,6 +4230,14 @@ ui::Dataspace Layer::getDataSpace() const { return hasBufferOrSidebandStream() ? mBufferInfo.mDataspace : mDrawingState.dataspace; } +bool Layer::isFrontBuffered() const { + if (mBufferInfo.mBuffer == nullptr) { + return false; + } + + return mBufferInfo.mBuffer->getUsage() & AHARDWAREBUFFER_USAGE_FRONT_BUFFER; +} + ui::Dataspace Layer::translateDataspace(ui::Dataspace dataspace) { ui::Dataspace updatedDataspace = dataspace; // translate legacy dataspaces to modern dataspaces diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index dd91adcba7..46aa5214c3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -342,6 +342,8 @@ public: // ui::Dataspace getDataSpace() const; + virtual bool isFrontBuffered() const; + virtual sp getCompositionEngineLayerFE() const; virtual sp copyCompositionEngineLayerFE() const; sp getCompositionEngineLayerFE(const frontend::LayerHierarchy::TraversalPath&); @@ -915,14 +917,13 @@ public: void recordLayerHistoryBufferUpdate(const scheduler::LayerProps&, nsecs_t now); void recordLayerHistoryAnimationTx(const scheduler::LayerProps&, nsecs_t now); auto getLayerProps() const { - return scheduler::LayerProps{ - .visible = isVisible(), - .bounds = getBounds(), - .transform = getTransform(), - .setFrameRateVote = getFrameRateForLayerTree(), - .frameRateSelectionPriority = getFrameRateSelectionPriority(), - .isSmallDirty = mSmallDirty, - }; + return scheduler::LayerProps{.visible = isVisible(), + .bounds = getBounds(), + .transform = getTransform(), + .setFrameRateVote = getFrameRateForLayerTree(), + .frameRateSelectionPriority = getFrameRateSelectionPriority(), + .isSmallDirty = mSmallDirty, + .isFrontBuffered = isFrontBuffered()}; }; bool hasBuffer() const { return mBufferInfo.mBuffer != nullptr; } void setTransformHint(std::optional transformHint) { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 21bbb08c1c..8fc9cba794 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -51,6 +51,11 @@ bool isLayerActive(const LayerInfo& info, nsecs_t threshold) { return true; } + // Make all front buffered layers active + if (FlagManager::getInstance().vrr_config() && info.isFrontBuffered() && info.isVisible()) { + return true; + } + return info.isVisible() && info.getLastUpdatedTime() >= threshold; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 54e9022add..8d18769e5a 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -334,6 +334,14 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec return votes; } + // Vote for max refresh rate whenever we're front-buffered. + if (FlagManager::getInstance().vrr_config() && isFrontBuffered()) { + ATRACE_FORMAT_INSTANT("front buffered"); + ALOGV("%s is front-buffered", mName.c_str()); + votes.push_back({LayerHistory::LayerVoteType::Max, Fps()}); + return votes; + } + const LayerInfo::Frequent frequent = isFrequent(now); mIsFrequencyConclusive = frequent.isConclusive; if (!frequent.isFrequent) { @@ -394,6 +402,10 @@ int32_t LayerInfo::getFrameRateSelectionPriority() const { return mLayerProps->frameRateSelectionPriority; } +bool LayerInfo::isFrontBuffered() const { + return mLayerProps->isFrontBuffered; +} + FloatRect LayerInfo::getBounds() const { return mLayerProps->bounds; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 7d3cffabf7..03ab0df3cd 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -200,6 +200,7 @@ public: FrameRate getSetFrameRateVote() const; bool isVisible() const; int32_t getFrameRateSelectionPriority() const; + bool isFrontBuffered() const; FloatRect getBounds() const; ui::Transform getTransform() const; @@ -360,6 +361,7 @@ struct LayerProps { LayerInfo::FrameRate setFrameRateVote; int32_t frameRateSelectionPriority = -1; bool isSmallDirty = false; + bool isFrontBuffered = false; }; } // namespace scheduler diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 62eb17d2e7..d5e1f53cc6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2247,6 +2247,7 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) { .setFrameRateVote = snapshot->frameRate, .frameRateSelectionPriority = snapshot->frameRateSelectionPriority, .isSmallDirty = snapshot->isSmallDirty, + .isFrontBuffered = snapshot->isFrontBuffered(), }; if (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) { @@ -4880,6 +4881,7 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin .transform = layer->getTransform(), .setFrameRateVote = layer->getFrameRateForLayerTree(), .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(), + .isFrontBuffered = layer->isFrontBuffered(), }; layer->recordLayerHistoryAnimationTx(layerProps, now); } diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index e8831ab51f..7c95e5de34 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -925,6 +925,43 @@ TEST_F(LayerHistoryTest, infrequentAnimatingLayer) { EXPECT_EQ(1, animatingLayerCount(time)); } +TEST_F(LayerHistoryTest, frontBufferedLayerVotesMax) { + SET_FLAG_FOR_TEST(flags::vrr_config, true); + auto layer = createLayer(); + + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); + EXPECT_CALL(*layer, isFrontBuffered()).WillRepeatedly(Return(true)); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // layer is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer->getSequence(), layer->getLayerProps(), time, time, + LayerHistory::LayerUpdateType::Buffer); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + } + + ASSERT_EQ(1, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(1, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); +} + TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) { auto layer = createLayer(); diff --git a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp index 11072bc4c9..5a03c597f5 100644 --- a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp @@ -21,6 +21,7 @@ #include +#include "FlagUtils.h" #include "FpsOps.h" #include "Scheduler/LayerHistory.h" #include "Scheduler/LayerInfo.h" @@ -28,6 +29,8 @@ #include "TestableSurfaceFlinger.h" #include "mock/MockSchedulerCallback.h" +#include + namespace android::scheduler { using android::mock::createDisplayMode; @@ -67,6 +70,8 @@ protected: namespace { +using namespace com::android::graphics::surfaceflinger; + TEST_F(LayerInfoTest, prefersPresentTime) { std::deque frameTimes; constexpr auto kExpectedFps = 50_Hz; @@ -261,5 +266,18 @@ TEST_F(LayerInfoTest, getRefreshRateVote_noData) { ASSERT_EQ(actualVotes[0].fps, vote.fps); } +TEST_F(LayerInfoTest, isFrontBuffered) { + SET_FLAG_FOR_TEST(flags::vrr_config, true); + ASSERT_FALSE(layerInfo.isFrontBuffered()); + + LayerProps prop = {.isFrontBuffered = true}; + layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop); + ASSERT_TRUE(layerInfo.isFrontBuffered()); + + prop.isFrontBuffered = false; + layerInfo.setLastPresentTime(0, 0, LayerHistory::LayerUpdateType::Buffer, true, prop); + ASSERT_FALSE(layerInfo.isFrontBuffered()); +} + } // namespace } // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index e784eb76f3..57babafac3 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -898,4 +898,24 @@ TEST_F(LayerSnapshotTest, setTrustedOverlayForNonVisibleInput) { gui::WindowInfo::InputConfig::TRUSTED_OVERLAY)); } +TEST_F(LayerSnapshotTest, isFrontBuffered) { + setBuffer(1, + std::make_shared( + 1U /*width*/, 1U /*height*/, 1ULL /* bufferId */, HAL_PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_HW_TEXTURE | AHARDWAREBUFFER_USAGE_FRONT_BUFFER /*usage*/)); + + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + EXPECT_TRUE(getSnapshot(1)->isFrontBuffered()); + + setBuffer(1, + std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_HW_TEXTURE /*usage*/)); + + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + EXPECT_FALSE(getSnapshot(1)->isFrontBuffered()); +} + } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index 4cc78febee..3dfb649a02 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -37,6 +37,7 @@ public: MOCK_CONST_METHOD0(getDefaultFrameRateCompatibility, scheduler::FrameRateCompatibility()); MOCK_CONST_METHOD0(getOwnerUid, uid_t()); MOCK_CONST_METHOD0(getDataSpace, ui::Dataspace()); + MOCK_METHOD(bool, isFrontBuffered, (), (const, override)); }; } // namespace android::mock -- cgit v1.2.3-59-g8ed1b From 494a2e40b6fb1d9703735aa518ed6283e6d026ca Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 10 Nov 2023 17:21:19 -0800 Subject: Added contentSize to WindowInfo In order to compute TPL using WindowInfoListener, it needs contentSize to know the original bounds vs the displayed bounds. This is to ensure the crop is factored in when computing percentage visible. Test: WindowInfo Bug: 290795410 Change-Id: Ic5a69d6ce9c4c436a63e51d7ce086960426d688b --- libs/gui/WindowInfo.cpp | 9 +++++++-- libs/gui/include/gui/WindowInfo.h | 4 ++++ libs/gui/tests/WindowInfo_test.cpp | 3 +++ services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp | 3 +++ services/surfaceflinger/Layer.cpp | 4 ++++ 5 files changed, 21 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp index 2eb6bd670d..6a4460b650 100644 --- a/libs/gui/WindowInfo.cpp +++ b/libs/gui/WindowInfo.cpp @@ -66,8 +66,9 @@ bool WindowInfo::overlaps(const WindowInfo* other) const { bool WindowInfo::operator==(const WindowInfo& info) const { return info.token == token && info.id == id && info.name == name && info.dispatchingTimeout == dispatchingTimeout && info.frame == frame && - info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor && - info.transform == transform && info.touchableRegion.hasSameRects(touchableRegion) && + info.contentSize == contentSize && info.surfaceInset == surfaceInset && + info.globalScaleFactor == globalScaleFactor && info.transform == transform && + info.touchableRegion.hasSameRects(touchableRegion) && info.touchOcclusionMode == touchOcclusionMode && info.ownerPid == ownerPid && info.ownerUid == ownerUid && info.packageName == packageName && info.inputConfig == inputConfig && info.displayId == displayId && @@ -101,6 +102,8 @@ status_t WindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->writeInt32( static_cast>(layoutParamsType)) ?: parcel->write(frame) ?: + parcel->writeInt32(contentSize.width) ?: + parcel->writeInt32(contentSize.height) ?: parcel->writeInt32(surfaceInset) ?: parcel->writeFloat(globalScaleFactor) ?: parcel->writeFloat(alpha) ?: @@ -150,6 +153,8 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { status = parcel->readInt32(&lpFlags) ?: parcel->readInt32(&lpType) ?: parcel->read(frame) ?: + parcel->readInt32(&contentSize.width) ?: + parcel->readInt32(&contentSize.height) ?: parcel->readInt32(&surfaceInset) ?: parcel->readFloat(&globalScaleFactor) ?: parcel->readFloat(&alpha) ?: diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index bd2eb7413b..dcc38d7564 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -196,6 +197,9 @@ struct WindowInfo : public Parcelable { /* These values are filled in by SurfaceFlinger. */ Rect frame = Rect::INVALID_RECT; + // The real size of the content, excluding any crop. If no buffer is rendered, this is 0,0 + ui::Size contentSize = ui::Size(0, 0); + /* * SurfaceFlinger consumes this value to shrink the computed frame. This is * different from shrinking the touchable region in that it DOES shift the coordinate diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp index f2feaefa13..5eb5d3bff0 100644 --- a/libs/gui/tests/WindowInfo_test.cpp +++ b/libs/gui/tests/WindowInfo_test.cpp @@ -28,6 +28,7 @@ namespace android { using gui::InputApplicationInfo; using gui::TouchOcclusionMode; using gui::WindowInfo; +using ui::Size; namespace test { @@ -53,6 +54,7 @@ TEST(WindowInfo, Parcelling) { i.layoutParamsType = WindowInfo::Type::INPUT_METHOD; i.dispatchingTimeout = 12s; i.frame = Rect(93, 34, 16, 19); + i.contentSize = Size(10, 40); i.surfaceInset = 17; i.globalScaleFactor = 0.3; i.alpha = 0.7; @@ -83,6 +85,7 @@ TEST(WindowInfo, Parcelling) { ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType); ASSERT_EQ(i.dispatchingTimeout, i2.dispatchingTimeout); ASSERT_EQ(i.frame, i2.frame); + ASSERT_EQ(i.contentSize, i2.contentSize); ASSERT_EQ(i.surfaceInset, i2.surfaceInset); ASSERT_EQ(i.globalScaleFactor, i2.globalScaleFactor); ASSERT_EQ(i.alpha, i2.alpha); diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 2a0857d4dd..9476ff4932 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -739,6 +739,7 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a !snapshot.changes.test(RequestedLayerState::Changes::Created)) { if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry | + RequestedLayerState::Changes::BufferSize | RequestedLayerState::Changes::Input)) { updateInput(snapshot, requested, parentSnapshot, path, args); } @@ -1095,6 +1096,8 @@ void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY; } + snapshot.inputInfo.contentSize = snapshot.croppedBufferSize.getSize(); + // If the layer is a clone, we need to crop the input region to cloned root to prevent // touches from going outside the cloned area. if (path.isClone()) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 66ea15ca2d..3ca83e0c47 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -136,6 +136,7 @@ using frontend::RoundedCornerState; using gui::GameMode; using gui::LayerMetadata; using gui::WindowInfo; +using ui::Size; using PresentState = frametimeline::SurfaceFrame::PresentState; @@ -2591,6 +2592,9 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) { } } + Rect bufferSize = getBufferSize(getDrawingState()); + info.contentSize = Size(bufferSize.width(), bufferSize.height()); + return info; } -- cgit v1.2.3-59-g8ed1b From 21d94322a3bec4b8f16010b91eb1da564c345da7 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 17 Oct 2023 19:51:39 +0000 Subject: Assign previous release fence to previous frame ID ...as otherwise the release timestamps for EGL/Vk timing apis are shifted by one frame. Bug: 295456126 Bug: 301055892 Bug: 303385401 Bug: 310927247 Test: Log and inspect timestamps Change-Id: If1d8a525053591f15b95aeec8dc0bad8a13e6833 --- libs/gui/BLASTBufferQueue.cpp | 24 ++++-- libs/gui/ITransactionCompletedListener.cpp | 14 ++++ libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp | 4 +- libs/gui/include/gui/BLASTBufferQueue.h | 4 +- .../include/gui/ITransactionCompletedListener.h | 7 +- libs/gui/libgui_flags.aconfig | 7 ++ libs/gui/tests/BLASTBufferQueue_test.cpp | 92 +++++++++++++++++++++- services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/Layer.h | 1 + .../surfaceflinger/TransactionCallbackInvoker.cpp | 2 +- .../surfaceflinger/TransactionCallbackInvoker.h | 1 + 11 files changed, 148 insertions(+), 16 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 8d0331ebb5..f317a2eea0 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -41,6 +41,8 @@ #include #include +#include + using namespace com::android::graphics::libgui; using namespace std::chrono_literals; @@ -102,12 +104,11 @@ void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry } } -void BLASTBufferItemConsumer::updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, - const sp& glDoneFence, - const sp& presentFence, - const sp& prevReleaseFence, - CompositorTiming compositorTiming, - nsecs_t latchTime, nsecs_t dequeueReadyTime) { +void BLASTBufferItemConsumer::updateFrameTimestamps( + uint64_t frameNumber, uint64_t previousFrameNumber, nsecs_t refreshStartTime, + const sp& glDoneFence, const sp& presentFence, + const sp& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime, + nsecs_t dequeueReadyTime) { Mutex::Autolock lock(mMutex); // if the producer is not connected, don't bother updating, @@ -118,7 +119,15 @@ void BLASTBufferItemConsumer::updateFrameTimestamps(uint64_t frameNumber, nsecs_ std::shared_ptr releaseFenceTime = std::make_shared(prevReleaseFence); mFrameEventHistory.addLatch(frameNumber, latchTime); - mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime)); + if (flags::frametimestamps_previousrelease()) { + if (previousFrameNumber > 0) { + mFrameEventHistory.addRelease(previousFrameNumber, dequeueReadyTime, + std::move(releaseFenceTime)); + } + } else { + mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime)); + } + mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime); mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime, compositorTiming); @@ -364,6 +373,7 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp 0) { mBufferItemConsumer ->updateFrameTimestamps(stat.frameEventStats.frameNumber, + stat.frameEventStats.previousFrameNumber, stat.frameEventStats.refreshStartTime, stat.frameEventStats.gpuCompositionDoneFence, stat.presentFence, stat.previousReleaseFence, diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 29d64afb24..f5d19aac78 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -25,6 +25,10 @@ #include #include +#include + +using namespace com::android::graphics::libgui; + namespace android { namespace { // Anonymous @@ -49,6 +53,11 @@ status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { status_t err = output->writeUint64(frameNumber); if (err != NO_ERROR) return err; + if (flags::frametimestamps_previousrelease()) { + err = output->writeUint64(previousFrameNumber); + if (err != NO_ERROR) return err; + } + if (gpuCompositionDoneFence) { err = output->writeBool(true); if (err != NO_ERROR) return err; @@ -79,6 +88,11 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { status_t err = input->readUint64(&frameNumber); if (err != NO_ERROR) return err; + if (flags::frametimestamps_previousrelease()) { + err = input->readUint64(&previousFrameNumber); + if (err != NO_ERROR) return err; + } + bool hasFence = false; err = input->readBool(&hasFence); if (err != NO_ERROR) return err; diff --git a/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp b/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp index 17f4c630ce..2e270b721f 100644 --- a/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp +++ b/libs/gui/fuzzer/libgui_bufferQueue_fuzzer.cpp @@ -141,8 +141,8 @@ void BufferQueueFuzzer::invokeBlastBufferQueue() { CompositorTiming compTiming; sp previousFence = new Fence(memfd_create("pfd", MFD_ALLOW_SEALING)); sp gpuFence = new Fence(memfd_create("gfd", MFD_ALLOW_SEALING)); - FrameEventHistoryStats frameStats(frameNumber, gpuFence, compTiming, - mFdp.ConsumeIntegral(), + FrameEventHistoryStats frameStats(frameNumber, mFdp.ConsumeIntegral(), gpuFence, + compTiming, mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral()); std::vector stats; sp presentFence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING)); diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 892215ec32..0e1a505c69 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -50,8 +50,8 @@ public: void onDisconnect() override EXCLUDES(mMutex); void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override EXCLUDES(mMutex); - void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, - const sp& gpuCompositionDoneFence, + void updateFrameTimestamps(uint64_t frameNumber, uint64_t previousFrameNumber, + nsecs_t refreshStartTime, const sp& gpuCompositionDoneFence, const sp& presentFence, const sp& prevReleaseFence, CompositorTiming compositorTiming, nsecs_t latchTime, nsecs_t dequeueReadyTime) EXCLUDES(mMutex); diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 364a57b8dd..bc97cd0828 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -95,15 +95,18 @@ public: status_t readFromParcel(const Parcel* input) override; FrameEventHistoryStats() = default; - FrameEventHistoryStats(uint64_t fn, const sp& gpuCompFence, CompositorTiming compTiming, + FrameEventHistoryStats(uint64_t frameNumber, uint64_t previousFrameNumber, + const sp& gpuCompFence, CompositorTiming compTiming, nsecs_t refreshTime, nsecs_t dequeueReadyTime) - : frameNumber(fn), + : frameNumber(frameNumber), + previousFrameNumber(previousFrameNumber), gpuCompositionDoneFence(gpuCompFence), compositorTiming(compTiming), refreshStartTime(refreshTime), dequeueReadyTime(dequeueReadyTime) {} uint64_t frameNumber; + uint64_t previousFrameNumber; sp gpuCompositionDoneFence; CompositorTiming compositorTiming; nsecs_t refreshStartTime; diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig index a16be786be..b081030c9f 100644 --- a/libs/gui/libgui_flags.aconfig +++ b/libs/gui/libgui_flags.aconfig @@ -8,3 +8,10 @@ flag { is_fixed_read_only: true } +flag { + name: "frametimestamps_previousrelease" + namespace: "core_graphics" + description: "Controls a fence fixup for timestamp apis" + bug: "310927247" + is_fixed_read_only: true +} diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 9893c7146e..ea7078dd05 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -42,9 +42,12 @@ #include +#include + using namespace std::chrono_literals; namespace android { +using namespace com::android::graphics::libgui; using Transaction = SurfaceComposerClient::Transaction; using android::hardware::graphics::common::V1_2::BufferUsage; @@ -1581,6 +1584,9 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { nsecs_t postedTimeB = 0; setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true); history.applyDelta(qbOutput.frameTimestamps); + + adapter.waitForCallback(2); + events = history.getFrame(1); ASSERT_NE(nullptr, events); @@ -1590,7 +1596,9 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { ASSERT_GE(events->postedTime, postedTimeA); ASSERT_GE(events->latchTime, postedTimeA); - ASSERT_GE(events->dequeueReadyTime, events->latchTime); + if (flags::frametimestamps_previousrelease()) { + ASSERT_EQ(events->dequeueReadyTime, FrameEvents::TIMESTAMP_PENDING); + } ASSERT_NE(nullptr, events->gpuCompositionDoneFence); ASSERT_NE(nullptr, events->displayPresentFence); ASSERT_NE(nullptr, events->releaseFence); @@ -1602,6 +1610,50 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeB); + // Now do the same as above with a third buffer, so that timings related to + // buffer releases make it back to the first frame. + nsecs_t requestedPresentTimeC = 0; + nsecs_t postedTimeC = 0; + setUpAndQueueBuffer(igbProducer, &requestedPresentTimeC, &postedTimeC, &qbOutput, true); + history.applyDelta(qbOutput.frameTimestamps); + + adapter.waitForCallback(3); + + // Check the first frame... + events = history.getFrame(1); + ASSERT_NE(nullptr, events); + ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeA); + ASSERT_GE(events->latchTime, postedTimeA); + // Now dequeueReadyTime is valid, because the release timings finally + // propaged to queueBuffer() + ASSERT_GE(events->dequeueReadyTime, events->latchTime); + ASSERT_NE(nullptr, events->gpuCompositionDoneFence); + ASSERT_NE(nullptr, events->displayPresentFence); + ASSERT_NE(nullptr, events->releaseFence); + + // ...and the second + events = history.getFrame(2); + ASSERT_NE(nullptr, events); + ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeB); + ASSERT_GE(events->latchTime, postedTimeB); + if (flags::frametimestamps_previousrelease()) { + ASSERT_EQ(events->dequeueReadyTime, FrameEvents::TIMESTAMP_PENDING); + } + ASSERT_NE(nullptr, events->gpuCompositionDoneFence); + ASSERT_NE(nullptr, events->displayPresentFence); + ASSERT_NE(nullptr, events->releaseFence); + + // ...and finally the third! + events = history.getFrame(3); + ASSERT_NE(nullptr, events); + ASSERT_EQ(3, events->frameNumber); + ASSERT_EQ(requestedPresentTimeC, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeC); + // wait for any callbacks that have not been received adapter.waitForCallbacks(); } @@ -1660,6 +1712,8 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { setUpAndQueueBuffer(igbProducer, &requestedPresentTimeC, &postedTimeC, &qbOutput, true); history.applyDelta(qbOutput.frameTimestamps); + adapter.waitForCallback(3); + // frame number, requestedPresentTime, and postTime should not have changed ASSERT_EQ(1, events->frameNumber); ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); @@ -1672,6 +1726,42 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) { ASSERT_FALSE(events->hasDisplayPresentInfo()); ASSERT_FALSE(events->hasReleaseInfo()); + // we should also have gotten values for the presented frame + events = history.getFrame(2); + ASSERT_NE(nullptr, events); + ASSERT_EQ(2, events->frameNumber); + ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeB); + ASSERT_GE(events->latchTime, postedTimeB); + + if (flags::frametimestamps_previousrelease()) { + ASSERT_EQ(events->dequeueReadyTime, FrameEvents::TIMESTAMP_PENDING); + } + ASSERT_NE(nullptr, events->gpuCompositionDoneFence); + ASSERT_NE(nullptr, events->displayPresentFence); + ASSERT_NE(nullptr, events->releaseFence); + + // Queue another buffer to check for timestamps that came late + nsecs_t requestedPresentTimeD = 0; + nsecs_t postedTimeD = 0; + setUpAndQueueBuffer(igbProducer, &requestedPresentTimeD, &postedTimeD, &qbOutput, true); + history.applyDelta(qbOutput.frameTimestamps); + + adapter.waitForCallback(4); + + // frame number, requestedPresentTime, and postTime should not have changed + events = history.getFrame(1); + ASSERT_EQ(1, events->frameNumber); + ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); + ASSERT_GE(events->postedTime, postedTimeA); + + // a valid latchtime and pre and post composition info should not be set for the dropped frame + ASSERT_FALSE(events->hasLatchInfo()); + ASSERT_FALSE(events->hasDequeueReadyInfo()); + ASSERT_FALSE(events->hasGpuCompositionDoneInfo()); + ASSERT_FALSE(events->hasDisplayPresentInfo()); + ASSERT_FALSE(events->hasReleaseInfo()); + // we should also have gotten values for the presented frame events = history.getFrame(2); ASSERT_NE(nullptr, events); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 66ea15ca2d..63dba93792 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -165,6 +165,7 @@ Layer::Layer(const surfaceflinger::LayerCreationArgs& args) mDrawingState.sequence = 0; mDrawingState.transform.set(0, 0); mDrawingState.frameNumber = 0; + mDrawingState.previousFrameNumber = 0; mDrawingState.barrierFrameNumber = 0; mDrawingState.producerId = 0; mDrawingState.barrierProducerId = 0; @@ -2931,7 +2932,6 @@ void Layer::onLayerDisplayed(ftl::SharedFuture futureFenceResult, break; } } - if (ch != nullptr) { ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; ch->previousReleaseFences.emplace_back(std::move(futureFenceResult)); @@ -2940,6 +2940,10 @@ void Layer::onLayerDisplayed(ftl::SharedFuture futureFenceResult, if (mBufferInfo.mBuffer) { mPreviouslyPresentedLayerStacks.push_back(layerStack); } + + if (mDrawingState.frameNumber > 0) { + mDrawingState.previousFrameNumber = mDrawingState.frameNumber; + } } void Layer::onSurfaceFrameCreated( @@ -3144,6 +3148,7 @@ void Layer::releasePreviousBuffer() { void Layer::resetDrawingStateBufferInfo() { mDrawingState.producerId = 0; mDrawingState.frameNumber = 0; + mDrawingState.previousFrameNumber = 0; mDrawingState.releaseBufferListener = nullptr; mDrawingState.buffer = nullptr; mDrawingState.acquireFence = sp::make(-1); @@ -3420,6 +3425,7 @@ bool Layer::setTransactionCompletedListeners(const std::vectoracquireTimeOrFence = mCallbackHandleAcquireTimeOrFence; handle->frameNumber = mDrawingState.frameNumber; + handle->previousFrameNumber = mDrawingState.previousFrameNumber; // Store so latched time and release fence can be set mDrawingState.callbackHandles.push_back(handle); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f71591044d..28168c3f65 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -138,6 +138,7 @@ public: ui::Dataspace dataspace; uint64_t frameNumber; + uint64_t previousFrameNumber; // high watermark framenumber to use to check for barriers to protect ourselves // from out of order transactions uint64_t barrierFrameNumber; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 3587a726cd..6a155c17df 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -158,7 +158,7 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle->previousReleaseFence = prevFence; handle->previousReleaseFences.clear(); - FrameEventHistoryStats eventStats(handle->frameNumber, + FrameEventHistoryStats eventStats(handle->frameNumber, handle->previousFrameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, handle->dequeueReadyTime); diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 3074795f62..245398f2f4 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -56,6 +56,7 @@ public: nsecs_t refreshStartTime = 0; nsecs_t dequeueReadyTime = 0; uint64_t frameNumber = 0; + uint64_t previousFrameNumber = 0; ReleaseCallbackId previousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; }; -- cgit v1.2.3-59-g8ed1b From 8a06fb7d4d68198308987e04c677d3a1b02b5c40 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Thu, 16 Nov 2023 22:07:13 +0000 Subject: Use ro.board.api_level instead of ro.vndk.version VNDK's getting deprecated so ro.board.api_level is the right sysprop to use for vendor api version. Bug: 311267616 Test: builds Change-Id: Ie73bef793cd811d16b9b781b2bf38d9a52558547 --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0c0639ee83..4c2da91afe 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3635,7 +3635,7 @@ void Layer::gatherBufferInfo() { // to upsert RenderEngine's caches. Put in a special workaround to be backwards // compatible with old vendors, with a ticking clock. static const int32_t kVendorVersion = - base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__); + base::GetIntProperty("ro.board.api_level", __ANDROID_API_FUTURE__); if (const auto format = static_cast( mBufferInfo.mBuffer->getPixelFormat()); -- cgit v1.2.3-59-g8ed1b From a021bb0f099587dc41b6eec042a004be9404cde1 Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Mon, 20 Nov 2023 21:51:09 -0800 Subject: Logic for selection strategy "DoNotPropagate" This logic is for the new FrameRateSelectionStrategy::DoNotPropagate. The default behavior ("Self") is to propagate parent vote to children that has no votes, but if a layer has "DoNotPropagate", it will not propagate its vote to children. Bug: 309687765 Test: atest libsurfaceflinger_unittest Test: atest CtsSurfaceControlTestsStaging Change-Id: I284b639f2b1902c5e9d3dcd08ceaf3f76b73451e --- libs/nativewindow/include/system/window.h | 15 +++- .../FrontEnd/LayerSnapshotBuilder.cpp | 22 ++++-- services/surfaceflinger/Layer.cpp | 11 +-- services/surfaceflinger/Layer.h | 5 ++ services/surfaceflinger/Scheduler/LayerInfo.cpp | 2 + services/surfaceflinger/Scheduler/LayerInfo.h | 3 +- .../unittests/FrameRateSelectionStrategyTest.cpp | 58 +++++++++++++- .../tests/unittests/LayerSnapshotTest.cpp | 88 ++++++++++++++++++++++ 8 files changed, 186 insertions(+), 18 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index b068f4807c..05838128d8 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1103,7 +1103,12 @@ enum { enum { /** * Default value. The layer uses its own frame rate specifications, assuming it has any - * specifications, instead of its parent's. + * specifications, instead of its parent's. If it does not have its own frame rate + * specifications, it will try to use its parent's. + * + * However, FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN on an ancestor layer + * supersedes this behavior, meaning that this layer will inherit the frame rate specifications + * of that ancestor layer. */ ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF = 0, @@ -1114,6 +1119,14 @@ enum { * behavior for itself. */ ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN = 1, + + /** + * The layer's frame rate specifications will never propagate to its descendant + * layers. + * FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN on an ancestor layer supersedes + * this behavior. + */ + ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_DO_NOT_PROPAGATE = 2, }; static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 743cbf3cb1..a57cd0ad35 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -814,9 +814,12 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a RequestedLayerState::Changes::Hierarchy) || snapshot.changes.any(RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::Hierarchy)) { - bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy == + const bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy == scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren; - if (!requested.requestedFrameRate.isValid() || shouldOverrideChildren) { + const bool propagationAllowed = parentSnapshot.frameRateSelectionStrategy != + scheduler::LayerInfo::FrameRateSelectionStrategy::DoNotPropagate; + if ((!requested.requestedFrameRate.isValid() && propagationAllowed) || + shouldOverrideChildren) { snapshot.inheritedFrameRate = parentSnapshot.inheritedFrameRate; } else { snapshot.inheritedFrameRate = requested.requestedFrameRate; @@ -828,12 +831,15 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a } if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionStrategyChanged) { - const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy( - requested.frameRateSelectionStrategy); - snapshot.frameRateSelectionStrategy = - strategy == scheduler::LayerInfo::FrameRateSelectionStrategy::Self - ? parentSnapshot.frameRateSelectionStrategy - : strategy; + if (parentSnapshot.frameRateSelectionStrategy == + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren) { + snapshot.frameRateSelectionStrategy = + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren; + } else { + const auto strategy = scheduler::LayerInfo::convertFrameRateSelectionStrategy( + requested.frameRateSelectionStrategy); + snapshot.frameRateSelectionStrategy = strategy; + } } if (forceUpdate || snapshot.clientChanges & layer_state_t::eFrameRateSelectionPriority) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f587e9db39..602dae0feb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1273,14 +1273,15 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overr auto now = systemTime(); *transactionNeeded |= setFrameRateForLayerTreeLegacy(frameRate, now); - // The frame rate is propagated to the children + // The frame rate is propagated to the children by default, but some properties may override it. bool childrenHaveFrameRate = false; + const bool overrideChildrenFrameRate = overrideChildren || shouldOverrideChildrenFrameRate(); + const bool canPropagateFrameRate = shouldPropagateFrameRate() || overrideChildrenFrameRate; for (const sp& child : mCurrentChildren) { childrenHaveFrameRate |= - child->propagateFrameRateForLayerTree(frameRate, - overrideChildren || - shouldOverrideChildrenFrameRate(), - transactionNeeded); + child->propagateFrameRateForLayerTree(canPropagateFrameRate ? frameRate + : FrameRate(), + overrideChildrenFrameRate, transactionNeeded); } // If we don't have a valid frame rate specification, but the children do, we set this diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 28168c3f65..790dfb569e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1178,6 +1178,11 @@ private: FrameRateSelectionStrategy::OverrideChildren; } + bool shouldPropagateFrameRate() const { + return getDrawingState().frameRateSelectionStrategy != + FrameRateSelectionStrategy::DoNotPropagate; + } + // Cached properties computed from drawing state // Effective transform taking into account parent transforms and any parent scaling, which is // a transform from the current layer coordinate space to display(screen) coordinate space. diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index bf3a7bc8b7..db0aebf2a2 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -530,6 +530,8 @@ LayerInfo::FrameRateSelectionStrategy LayerInfo::convertFrameRateSelectionStrate return FrameRateSelectionStrategy::Self; case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN: return FrameRateSelectionStrategy::OverrideChildren; + case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_DO_NOT_PROPAGATE: + return FrameRateSelectionStrategy::DoNotPropagate; default: LOG_ALWAYS_FATAL("Invalid frame rate selection strategy value %d", strategy); return FrameRateSelectionStrategy::Self; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index d24fc33491..c7b53fceae 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -83,8 +83,9 @@ public: enum class FrameRateSelectionStrategy { Self, OverrideChildren, + DoNotPropagate, - ftl_last = OverrideChildren + ftl_last = DoNotPropagate }; // Encapsulates the frame rate specifications of the layer. This information will be used diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp index 20ea0c080a..d791c4a3bc 100644 --- a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp @@ -49,6 +49,7 @@ protected: const FrameRate FRAME_RATE_VOTE1 = FrameRate(11_Hz, FrameRateCompatibility::Default); const FrameRate FRAME_RATE_VOTE2 = FrameRate(22_Hz, FrameRateCompatibility::Default); const FrameRate FRAME_RATE_VOTE3 = FrameRate(33_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_DEFAULT = FrameRate(Fps(), FrameRateCompatibility::Default); const FrameRate FRAME_RATE_TREE = FrameRate(Fps(), FrameRateCompatibility::NoVote); FrameRateSelectionStrategyTest(); @@ -102,7 +103,7 @@ TEST_P(FrameRateSelectionStrategyTest, SetAndGet) { layer->getDrawingState().frameRateSelectionStrategy); } -TEST_P(FrameRateSelectionStrategyTest, SetChildAndGetParent) { +TEST_P(FrameRateSelectionStrategyTest, SetChildOverrideChildren) { EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); const auto& layerFactory = GetParam(); @@ -126,7 +127,7 @@ TEST_P(FrameRateSelectionStrategyTest, SetChildAndGetParent) { child2->getDrawingState().frameRateSelectionStrategy); } -TEST_P(FrameRateSelectionStrategyTest, SetParentAndGet) { +TEST_P(FrameRateSelectionStrategyTest, SetParentOverrideChildren) { EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); const auto& layerFactory = GetParam(); @@ -136,7 +137,6 @@ TEST_P(FrameRateSelectionStrategyTest, SetParentAndGet) { addChild(layer1, layer2); addChild(layer2, layer3); - layer1->setFrameRate(FRAME_RATE_VOTE1.vote); layer1->setFrameRate(FRAME_RATE_VOTE1.vote); layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); layer2->setFrameRate(FRAME_RATE_VOTE2.vote); @@ -168,5 +168,57 @@ TEST_P(FrameRateSelectionStrategyTest, SetParentAndGet) { layer3->getDrawingState().frameRateSelectionStrategy); } +TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndDoNotPropagate) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto layer1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto layer2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto layer3 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + addChild(layer1, layer2); + addChild(layer2, layer3); + + layer1->setFrameRate(FRAME_RATE_VOTE1.vote); + layer2->setFrameRate(FRAME_RATE_VOTE2.vote); + layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::DoNotPropagate); + commitTransaction(); + + EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::DoNotPropagate, + layer2->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_DEFAULT, layer3->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer3->getDrawingState().frameRateSelectionStrategy); + + layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + commitTransaction(); + + EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, layer2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::DoNotPropagate, + layer2->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer3->getDrawingState().frameRateSelectionStrategy); + + layer1->setFrameRate(FRAME_RATE_DEFAULT.vote); + commitTransaction(); + + EXPECT_EQ(FRAME_RATE_TREE, layer1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::DoNotPropagate, + layer2->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE2, layer3->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer3->getDrawingState().frameRateSelectionStrategy); +} + } // namespace } // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 16143e3a7f..40d6ad31f4 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -928,6 +928,94 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithCategory) { EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); } +TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithOverrideChildrenAndDoNotPropagate) { + // ROOT + // ├── 1 + // │ ├── 11 (frame rate set to 11.f with strategy DoNotPropagate) + // │ │ └── 111 (frame rate is not inherited) + // │ ├── 12 (frame rate set to 244.f) + // │ │ ├── 121 + // │ │ └── 122 (strategy OverrideChildren and inherits frame rate 244.f) + // │ │ └── 1221 (frame rate set to 123.f but should be overridden by layer 122) + // │ └── 13 + // └── 2 + setFrameRate(11, 11.f, 0, 0); + setFrameRateSelectionStrategy(11, 2 /* DoNotPropagate */); + setFrameRate(12, 244.f, 0, 0); + setFrameRateSelectionStrategy(122, 1 /* OverrideChildren */); + setFrameRate(1221, 123.f, 0, 0); + + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + // verify parent 1 gets no vote + EXPECT_FALSE(getSnapshot({.id = 1})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, + scheduler::FrameRateCompatibility::NoVote); + EXPECT_EQ(getSnapshot({.id = 1})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 11.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::DoNotPropagate); + EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify layer 11 does does not propagate its framerate to 111. + EXPECT_FALSE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); + EXPECT_EQ(getSnapshot({.id = 111})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify layer 12 and all descendants (121, 122, 1221) get the requested vote + EXPECT_EQ(getSnapshot({.id = 12})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 12})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 121})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 121})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + EXPECT_TRUE(getSnapshot({.id = 121})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 122})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.rate.getValue(), 244.f); + EXPECT_EQ(getSnapshot({.id = 1221})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // ROOT + // ├── 1 (frame rate set to 1.f with strategy OverrideChildren) + // │ ├── 11 (frame rate set to 11.f with strategy DoNotPropagate, but overridden by 1) + // │ │ └── 111 (frame rate inherited from 11 due to override from 1) + // ⋮ ⋮ + setFrameRate(1, 1.f, 0, 0); + setFrameRateSelectionStrategy(1, 1 /* OverrideChildren */); + setFrameRate(11, 11.f, 0, 0); + setFrameRateSelectionStrategy(11, 2 /* DoNotPropagate */); + UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.rate.getValue(), 1.f); + EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, + scheduler::FrameRateCompatibility::Default); + EXPECT_EQ(getSnapshot({.id = 1})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); + + EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 1.f); + EXPECT_EQ(getSnapshot({.id = 11})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); + + // verify layer 11 does does not propagate its framerate to 111. + EXPECT_EQ(getSnapshot({.id = 111})->frameRate.vote.rate.getValue(), 1.f); + EXPECT_EQ(getSnapshot({.id = 111})->frameRateSelectionStrategy, + scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren); + EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); +} + TEST_F(LayerSnapshotTest, skipRoundCornersWhenProtected) { setRoundedCorners(1, 42.f); setRoundedCorners(2, 42.f); -- cgit v1.2.3-59-g8ed1b From 70f7b69bb8f69ed78526d304c0a165b5ca54141e Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Wed, 22 Nov 2023 11:24:02 -0800 Subject: native: Rename frame rate selection strategies SELF -> PROPAGATE (default) DO_NOT_PROPAGATE -> SELF No behavioral changes. Test: atest libsurfaceflinger_unittest Bug: 309687765 Change-Id: I055d827a45ecc7f566375425c42e745a41b751f9 --- libs/gui/LayerState.cpp | 2 +- libs/nativewindow/include/system/window.h | 26 +++++++++------- .../FrontEnd/LayerSnapshotBuilder.cpp | 2 +- .../FrontEnd/RequestedLayerState.cpp | 2 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/Scheduler/LayerInfo.cpp | 8 ++--- services/surfaceflinger/Scheduler/LayerInfo.h | 6 ++-- .../unittests/FrameRateSelectionStrategyTest.cpp | 30 +++++++++--------- .../tests/unittests/LayerSnapshotTest.cpp | 36 +++++++++++----------- 10 files changed, 60 insertions(+), 57 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index fd8fc8d123..97a82be5f5 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -86,7 +86,7 @@ layer_state_t::layer_state_t() defaultFrameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), frameRateCategory(ANATIVEWINDOW_FRAME_RATE_CATEGORY_DEFAULT), frameRateCategorySmoothSwitchOnly(false), - frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF), + frameRateSelectionStrategy(ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_PROPAGATE), fixedTransformHint(ui::Transform::ROT_INVALID), autoRefresh(false), isTrustedOverlay(false), diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 05838128d8..e41aa06541 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1104,29 +1104,33 @@ enum { /** * Default value. The layer uses its own frame rate specifications, assuming it has any * specifications, instead of its parent's. If it does not have its own frame rate - * specifications, it will try to use its parent's. + * specifications, it will try to use its parent's. It will propagate its specifications to any + * descendants that do not have their own. * * However, FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN on an ancestor layer - * supersedes this behavior, meaning that this layer will inherit the frame rate specifications - * of that ancestor layer. + * supersedes this behavior, meaning that this layer will inherit frame rate specifications + * regardless of whether it has its own. */ - ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF = 0, + ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_PROPAGATE = 0, /** * The layer's frame rate specifications will propagate to and override those of its descendant * layers. - * The layer with this strategy has the ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF - * behavior for itself. + * + * The layer itself has the FRAME_RATE_SELECTION_STRATEGY_PROPAGATE behavior. + * Thus, ancestor layer that also has the strategy + * FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN will override this layer's + * frame rate specifications. */ ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN = 1, /** - * The layer's frame rate specifications will never propagate to its descendant - * layers. - * FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN on an ancestor layer supersedes - * this behavior. + * The layer's frame rate specifications will not propagate to its descendant + * layers, even if the descendant layer has no frame rate specifications. + * However, FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN on an ancestor + * layer supersedes this behavior. */ - ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_DO_NOT_PROPAGATE = 2, + ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF = 2, }; static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate, diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index a57cd0ad35..a92cc03831 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -817,7 +817,7 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a const bool shouldOverrideChildren = parentSnapshot.frameRateSelectionStrategy == scheduler::LayerInfo::FrameRateSelectionStrategy::OverrideChildren; const bool propagationAllowed = parentSnapshot.frameRateSelectionStrategy != - scheduler::LayerInfo::FrameRateSelectionStrategy::DoNotPropagate; + scheduler::LayerInfo::FrameRateSelectionStrategy::Self; if ((!requested.requestedFrameRate.isValid() && propagationAllowed) || shouldOverrideChildren) { snapshot.inheritedFrameRate = parentSnapshot.inheritedFrameRate; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index b1a18aefb5..21172ca015 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -125,7 +125,7 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args) frameRateCategory = static_cast(FrameRateCategory::Default); frameRateCategorySmoothSwitchOnly = false; frameRateSelectionStrategy = - static_cast(scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + static_cast(scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); dataspace = ui::Dataspace::V0_SRGB; gameMode = gui::GameMode::Unsupported; requestedFrameRate = {}; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 602dae0feb..d654ada10f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -193,7 +193,7 @@ Layer::Layer(const surfaceflinger::LayerCreationArgs& args) mDrawingState.dropInputMode = gui::DropInputMode::NONE; mDrawingState.dimmingEnabled = true; mDrawingState.defaultFrameRateCompatibility = FrameRateCompatibility::Default; - mDrawingState.frameRateSelectionStrategy = FrameRateSelectionStrategy::Self; + mDrawingState.frameRateSelectionStrategy = FrameRateSelectionStrategy::Propagate; if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 790dfb569e..c772e0ea1b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1179,8 +1179,7 @@ private: } bool shouldPropagateFrameRate() const { - return getDrawingState().frameRateSelectionStrategy != - FrameRateSelectionStrategy::DoNotPropagate; + return getDrawingState().frameRateSelectionStrategy != FrameRateSelectionStrategy::Self; } // Cached properties computed from drawing state diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index db0aebf2a2..71ad45153f 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -526,12 +526,12 @@ FrameRateCategory LayerInfo::FrameRate::convertCategory(int8_t category) { LayerInfo::FrameRateSelectionStrategy LayerInfo::convertFrameRateSelectionStrategy( int8_t strategy) { switch (strategy) { - case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF: - return FrameRateSelectionStrategy::Self; + case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_PROPAGATE: + return FrameRateSelectionStrategy::Propagate; case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_OVERRIDE_CHILDREN: return FrameRateSelectionStrategy::OverrideChildren; - case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_DO_NOT_PROPAGATE: - return FrameRateSelectionStrategy::DoNotPropagate; + case ANATIVEWINDOW_FRAME_RATE_SELECTION_STRATEGY_SELF: + return FrameRateSelectionStrategy::Self; default: LOG_ALWAYS_FATAL("Invalid frame rate selection strategy value %d", strategy); return FrameRateSelectionStrategy::Self; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index c7b53fceae..c6ee69e355 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -81,11 +81,11 @@ public: using RefreshRateVotes = ftl::SmallVector; enum class FrameRateSelectionStrategy { - Self, + Propagate, OverrideChildren, - DoNotPropagate, + Self, - ftl_last = DoNotPropagate + ftl_last = Self }; // Encapsulates the frame rate specifications of the layer. This information will be used diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp index d791c4a3bc..5c742d7360 100644 --- a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp @@ -117,10 +117,10 @@ TEST_P(FrameRateSelectionStrategyTest, SetChildOverrideChildren) { child2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); commitTransaction(); EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, parent->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, child1->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, @@ -151,24 +151,24 @@ TEST_P(FrameRateSelectionStrategyTest, SetParentOverrideChildren) { EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, layer2->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer3->getDrawingState().frameRateSelectionStrategy); - layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::Self); + layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::Propagate); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer1->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, layer2->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE2, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer3->getDrawingState().frameRateSelectionStrategy); } -TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndDoNotPropagate) { +TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndSelf) { EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); const auto& layerFactory = GetParam(); @@ -180,17 +180,17 @@ TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndDoNotPropagate) { layer1->setFrameRate(FRAME_RATE_VOTE1.vote); layer2->setFrameRate(FRAME_RATE_VOTE2.vote); - layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::DoNotPropagate); + layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::Self); commitTransaction(); EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer1->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::DoNotPropagate, + EXPECT_EQ(FrameRateSelectionStrategy::Self, layer2->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_DEFAULT, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer3->getDrawingState().frameRateSelectionStrategy); layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); @@ -200,10 +200,10 @@ TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndDoNotPropagate) { EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, layer1->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE1, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::DoNotPropagate, + EXPECT_EQ(FrameRateSelectionStrategy::Self, layer2->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer3->getDrawingState().frameRateSelectionStrategy); layer1->setFrameRate(FRAME_RATE_DEFAULT.vote); @@ -213,10 +213,10 @@ TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndDoNotPropagate) { EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, layer1->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::DoNotPropagate, + EXPECT_EQ(FrameRateSelectionStrategy::Self, layer2->getDrawingState().frameRateSelectionStrategy); EXPECT_EQ(FRAME_RATE_VOTE2, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, + EXPECT_EQ(FrameRateSelectionStrategy::Propagate, layer3->getDrawingState().frameRateSelectionStrategy); } diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 40d6ad31f4..040a3bfb3e 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -814,24 +814,24 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategy) { EXPECT_EQ(getSnapshot({.id = 12})->frameRate.vote.type, scheduler::FrameRateCompatibility::NoVote); EXPECT_EQ(getSnapshot({.id = 12})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_FALSE(getSnapshot({.id = 121})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 121})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_EQ(getSnapshot({.id = 121})->frameRate.vote.type, scheduler::FrameRateCompatibility::Default); EXPECT_TRUE(getSnapshot({.id = 121})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 123.f); EXPECT_EQ(getSnapshot({.id = 122})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.rate.getValue(), 123.f); EXPECT_EQ(getSnapshot({.id = 1221})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); } @@ -904,12 +904,12 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithCategory) { scheduler::FrameRateCompatibility::NoVote); EXPECT_EQ(getSnapshot({.id = 12})->frameRate.category, FrameRateCategory::Default); EXPECT_EQ(getSnapshot({.id = 12})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_FALSE(getSnapshot({.id = 12})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 121})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_EQ(getSnapshot({.id = 121})->frameRate.category, FrameRateCategory::Default); EXPECT_EQ(getSnapshot({.id = 121})->frameRate.vote.type, scheduler::FrameRateCompatibility::Default); @@ -917,21 +917,21 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithCategory) { EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 123.f); EXPECT_EQ(getSnapshot({.id = 122})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.category, FrameRateCategory::Default); EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.vote.rate.getValue(), 123.f); EXPECT_EQ(getSnapshot({.id = 1221})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.category, FrameRateCategory::Default); EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate)); } -TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithOverrideChildrenAndDoNotPropagate) { +TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithOverrideChildrenAndSelf) { // ROOT // ├── 1 - // │ ├── 11 (frame rate set to 11.f with strategy DoNotPropagate) + // │ ├── 11 (frame rate set to 11.f with strategy Self) // │ │ └── 111 (frame rate is not inherited) // │ ├── 12 (frame rate set to 244.f) // │ │ ├── 121 @@ -940,7 +940,7 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithOverrideChildrenAndDoNot // │ └── 13 // └── 2 setFrameRate(11, 11.f, 0, 0); - setFrameRateSelectionStrategy(11, 2 /* DoNotPropagate */); + setFrameRateSelectionStrategy(11, 2 /* Self */); setFrameRate(12, 244.f, 0, 0); setFrameRateSelectionStrategy(122, 1 /* OverrideChildren */); setFrameRate(1221, 123.f, 0, 0); @@ -951,29 +951,29 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithOverrideChildrenAndDoNot EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.type, scheduler::FrameRateCompatibility::NoVote); EXPECT_EQ(getSnapshot({.id = 1})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 1})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_EQ(getSnapshot({.id = 11})->frameRate.vote.rate.getValue(), 11.f); EXPECT_EQ(getSnapshot({.id = 11})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::DoNotPropagate); + scheduler::LayerInfo::FrameRateSelectionStrategy::Self); EXPECT_TRUE(getSnapshot({.id = 11})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer 11 does does not propagate its framerate to 111. EXPECT_FALSE(getSnapshot({.id = 111})->frameRate.vote.rate.isValid()); EXPECT_EQ(getSnapshot({.id = 111})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 111})->changes.test(RequestedLayerState::Changes::FrameRate)); // verify layer 12 and all descendants (121, 122, 1221) get the requested vote EXPECT_EQ(getSnapshot({.id = 12})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 12})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 12})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_EQ(getSnapshot({.id = 121})->frameRate.vote.rate.getValue(), 244.f); EXPECT_EQ(getSnapshot({.id = 121})->frameRateSelectionStrategy, - scheduler::LayerInfo::FrameRateSelectionStrategy::Self); + scheduler::LayerInfo::FrameRateSelectionStrategy::Propagate); EXPECT_TRUE(getSnapshot({.id = 121})->changes.test(RequestedLayerState::Changes::FrameRate)); EXPECT_EQ(getSnapshot({.id = 122})->frameRate.vote.rate.getValue(), 244.f); @@ -988,13 +988,13 @@ TEST_F(LayerSnapshotTest, frameRateSelectionStrategyWithOverrideChildrenAndDoNot // ROOT // ├── 1 (frame rate set to 1.f with strategy OverrideChildren) - // │ ├── 11 (frame rate set to 11.f with strategy DoNotPropagate, but overridden by 1) + // │ ├── 11 (frame rate set to 11.f with strategy Self, but overridden by 1) // │ │ └── 111 (frame rate inherited from 11 due to override from 1) // ⋮ ⋮ setFrameRate(1, 1.f, 0, 0); setFrameRateSelectionStrategy(1, 1 /* OverrideChildren */); setFrameRate(11, 11.f, 0, 0); - setFrameRateSelectionStrategy(11, 2 /* DoNotPropagate */); + setFrameRateSelectionStrategy(11, 2 /* Self */); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); EXPECT_EQ(getSnapshot({.id = 1})->frameRate.vote.rate.getValue(), 1.f); -- cgit v1.2.3-59-g8ed1b From 77d406d3694cdcf28febc85ecc62e40554d191f3 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 22 Nov 2023 15:00:23 -0800 Subject: SF: add FrameRateCategory to dumpsys Test: manual Change-Id: I61872e7f1dd441c831212ffae519dbda1187176c --- services/surfaceflinger/Layer.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f587e9db39..9195b57886 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1718,10 +1718,18 @@ void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapsho StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); const auto frameRate = snapshot.frameRate; + std::string frameRateStr; + if (frameRate.vote.rate.isValid()) { + StringAppendF(&frameRateStr, "%.2f", frameRate.vote.rate.getValue()); + } if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "%s %15s %17s", to_string(frameRate.vote.rate).c_str(), + StringAppendF(&result, "%6s %15s %17s", frameRateStr.c_str(), ftl::enum_string(frameRate.vote.type).c_str(), ftl::enum_string(frameRate.vote.seamlessness).c_str()); + } else if (frameRate.category != FrameRateCategory::Default) { + StringAppendF(&result, "%6s %15s %17s", frameRateStr.c_str(), + (std::string("Cat::") + ftl::enum_string(frameRate.category)).c_str(), + ftl::enum_string(frameRate.vote.seamlessness).c_str()); } else { result.append(41, ' '); } -- cgit v1.2.3-59-g8ed1b From 3667800c553fddb1627b455d2cb0d32c258d2085 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Wed, 29 Nov 2023 16:56:17 +0000 Subject: SF: guard texture view update tolerance logic with small area allow list Make sure the texture view update tolerance logic for refresh rate heuristic only applies to apps in the small area detection allow list. Bug: 307419914 Test: presubmit Change-Id: Ieefdc4abe8c6ae8389035914fea4737e00cceeb4 --- services/surfaceflinger/Layer.cpp | 6 +++--- services/surfaceflinger/Scheduler/Scheduler.cpp | 2 +- services/surfaceflinger/Scheduler/Scheduler.h | 7 ++++--- .../surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp | 2 +- .../surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- .../tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp | 4 ++-- 7 files changed, 13 insertions(+), 12 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f587e9db39..b9561dcb0c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -3255,7 +3255,7 @@ bool Layer::setBuffer(std::shared_ptr& buffer, // If the layer had been updated a TextureView, this would make sure the present time could be // same to TextureView update when it's a small dirty, and get the correct heuristic rate. - if (mFlinger->mScheduler->supportSmallDirtyDetection()) { + if (mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) { if (mDrawingState.useVsyncIdForRefreshRateSelection) { mUsedVsyncIdForRefreshRateSelection = true; } @@ -3288,7 +3288,7 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro } } - if (!mFlinger->mScheduler->supportSmallDirtyDetection()) { + if (!mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) { return static_cast(0); } @@ -4431,7 +4431,7 @@ void Layer::updateLastLatchTime(nsecs_t latchTime) { void Layer::setIsSmallDirty(const Region& damageRegion, const ui::Transform& layerToDisplayTransform) { mSmallDirty = false; - if (!mFlinger->mScheduler->supportSmallDirtyDetection()) { + if (!mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) { return; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index b54f33451b..25d9f577de 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -1221,7 +1221,7 @@ void Scheduler::updateSmallAreaDetection( } void Scheduler::setSmallAreaDetectionThreshold(int32_t appId, float threshold) { - mSmallAreaDetectionAllowMappings.setThesholdForAppId(appId, threshold); + mSmallAreaDetectionAllowMappings.setThresholdForAppId(appId, threshold); } bool Scheduler::isSmallDirtyArea(int32_t appId, uint32_t dirtyArea) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index c78051a278..1773d090dc 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -320,9 +320,10 @@ public: bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) EXCLUDES(mPolicyLock); - // Returns true if the small dirty detection is enabled. - bool supportSmallDirtyDetection() const { - return mFeatures.test(Feature::kSmallDirtyContentDetection); + // Returns true if the small dirty detection is enabled for the appId. + bool supportSmallDirtyDetection(int32_t appId) { + return mFeatures.test(Feature::kSmallDirtyContentDetection) && + mSmallAreaDetectionAllowMappings.getThresholdForAppId(appId).has_value(); } // Injects a delay that is a fraction of the predicted frame duration for the next frame. diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp index 38c6da48f6..7510ebf2df 100644 --- a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp +++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp @@ -29,7 +29,7 @@ void SmallAreaDetectionAllowMappings::update( } } -void SmallAreaDetectionAllowMappings::setThesholdForAppId(int32_t appId, float threshold) { +void SmallAreaDetectionAllowMappings::setThresholdForAppId(int32_t appId, float threshold) { if (!isValidThreshold(threshold)) return; std::lock_guard lock(mLock); diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h index e10301c1e8..4ec5e3b5e4 100644 --- a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h +++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h @@ -28,7 +28,7 @@ class SmallAreaDetectionAllowMappings { public: void update(std::vector>& appIdThresholdMappings); - void setThesholdForAppId(int32_t appId, float threshold) EXCLUDES(mLock); + void setThresholdForAppId(int32_t appId, float threshold) EXCLUDES(mLock); std::optional getThresholdForAppId(int32_t uid) EXCLUDES(mLock); private: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c15e74f107..7049068e6b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2204,7 +2204,7 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) { continue; } - const bool updateSmallDirty = mScheduler->supportSmallDirtyDetection() && + const bool updateSmallDirty = FlagManager::getInstance().enable_small_area_detection() && ((snapshot->clientChanges & layer_state_t::eSurfaceDamageRegionChanged) || snapshot->changes.any(Changes::Geometry)); diff --git a/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp b/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp index 05f9eed30b..8615035483 100644 --- a/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp +++ b/services/surfaceflinger/tests/unittests/SmallAreaDetectionAllowMappingsTest.cpp @@ -44,8 +44,8 @@ TEST_F(SmallAreaDetectionAllowMappingsTest, testUpdate) { ASSERT_EQ(mMappings.getThresholdForAppId(kAppId2).value(), kThreshold2); } -TEST_F(SmallAreaDetectionAllowMappingsTest, testSetThesholdForAppId) { - mMappings.setThesholdForAppId(kAppId1, kThreshold1); +TEST_F(SmallAreaDetectionAllowMappingsTest, testSetThresholdForAppId) { + mMappings.setThresholdForAppId(kAppId1, kThreshold1); ASSERT_EQ(mMappings.getThresholdForAppId(kAppId1), kThreshold1); } -- cgit v1.2.3-59-g8ed1b From 83d9162e155887776e3336e3217ead4d7a58b559 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 8 Dec 2023 23:00:22 +0000 Subject: Fix crash when cloning layers Hack to disable legacy code which is showing up in some crash clusters. The code is obsolete and has no effect when frontend is enabled. Reduce some chaos/noise by avoiding this path when frontend is enabled. Fixes: 314858515 Test: presubmit Change-Id: I3244e9d8b240f567ae5b68bc8120d7669d962d54 --- services/surfaceflinger/Layer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f7800bb485..c8b1059b94 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2687,6 +2687,7 @@ Region Layer::getVisibleRegion(const DisplayDevice* display) const { } void Layer::setInitialValuesForClone(const sp& clonedFrom, uint32_t mirrorRootId) { + if (mFlinger->mLayerLifecycleManagerEnabled) return; mSnapshot->path.id = clonedFrom->getSequence(); mSnapshot->path.mirrorRootIds.emplace_back(mirrorRootId); -- cgit v1.2.3-59-g8ed1b