Loading services/surfaceflinger/RegionSamplingThread.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -344,12 +344,13 @@ void RegionSamplingThread::captureSample() { renderengine::impl::ExternalTexture::Usage:: WRITEABLE); } auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); constexpr bool kRegionSampling = true; constexpr bool kGrayscale = false; if (const auto fenceResult = mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, mFlinger.captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, buffer, kRegionSampling, kGrayscale, nullptr) .get(); fenceResult.ok()) { Loading services/surfaceflinger/RenderArea.h +15 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,21 @@ public: mRotationFlags(rotation), mLayerStackSpaceRect(layerStackRect) {} static std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> fromTraverseLayersLambda( std::function<void(const LayerVector::Visitor&)> traverseLayers) { return [traverseLayers = std::move(traverseLayers)]() { std::vector<std::pair<Layer*, sp<LayerFE>>> layers; traverseLayers([&](Layer* layer) { // Layer::prepareClientComposition uses the layer's snapshot to populate the // resulting LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings // are generated with the layer's current buffer and geometry. layer->updateSnapshot(true /* updateGeometry */); layers.emplace_back(layer, layer->copyCompositionEngineLayerFE()); }); return layers; }; } virtual ~RenderArea() = default; // Invoke drawLayers to render layers into the render area. Loading services/surfaceflinger/SurfaceFlinger.cpp +56 −65 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ #include "FrameTracer/FrameTracer.h" #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/LayerHandle.h" #include "FrontEnd/LayerSnapshot.h" #include "HdrLayerInfoReporter.h" #include "Layer.h" #include "LayerProtoHelper.h" Loading Loading @@ -2515,30 +2516,30 @@ void SurfaceFlinger::updateLayerGeometry() { mLayersPendingRefresh.clear(); } bool SurfaceFlinger::isHdrLayer(Layer* layer) const { 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) { auto buffer = layer->getBuffer(); if (buffer && (buffer->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) { if (snapshot.externalTexture && (snapshot.externalTexture->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) { return false; } } if (isHdrDataspace(layer->getDataSpace())) { if (isHdrDataspace(snapshot.dataspace)) { return true; } // If the layer is not allowed to be dimmed, treat it as HDR. WindowManager may disable // dimming in order to keep animations invoking SDR screenshots of HDR layers seamless. // Treat such tagged layers as HDR so that DisplayManagerService does not try to change // the screen brightness if (!layer->isDimmingEnabled()) { if (!snapshot.dimmingEnabled) { return true; } // RANGE_EXTENDED layers may identify themselves as being "HDR" via a desired sdr/hdr ratio if ((layer->getDataSpace() & (int32_t)Dataspace::RANGE_MASK) == if ((snapshot.dataspace & (int32_t)Dataspace::RANGE_MASK) == (int32_t)Dataspace::RANGE_EXTENDED && layer->getDesiredSdrHdrRatio() > 1.01f) { snapshot.desiredSdrHdrRatio > 1.01f) { return true; } return false; Loading Loading @@ -2666,13 +2667,14 @@ void SurfaceFlinger::postComposition(nsecs_t callTime) { int32_t maxArea = 0; mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) { const auto layerFe = layer->getCompositionEngineLayerFE(); if (layer->isVisible() && compositionDisplay->includesLayer(layer->getOutputFilter())) { if (isHdrLayer(layer)) { const frontend::LayerSnapshot& snapshot = *layer->getLayerSnapshot(); if (snapshot.isVisible && compositionDisplay->includesLayer(snapshot.outputFilter)) { if (isHdrLayer(snapshot)) { const auto* outputLayer = compositionDisplay->getOutputLayerForLayer(layerFe); if (outputLayer) { info.mergeDesiredRatio(layer->getDesiredSdrHdrRatio()); info.mergeDesiredRatio(snapshot.desiredSdrHdrRatio); info.numberOfHdrLayers++; const auto displayFrame = outputLayer->getState().displayFrame; const int32_t area = displayFrame.width() * displayFrame.height(); Loading Loading @@ -6418,8 +6420,9 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, auto traverseLayers = [this, args, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, args.uid, visitor); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); return fenceStatus(future.get()); Loading Loading @@ -6454,6 +6457,7 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); Loading @@ -6463,7 +6467,7 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, constexpr bool kAllowProtected = false; constexpr bool kGrayscale = false; auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, captureListener); return fenceStatus(future.get()); Loading @@ -6481,7 +6485,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, ui::Size reqSize; sp<Layer> parent; Rect crop(args.sourceCrop); std::unordered_set<sp<Layer>, SpHash<Layer>> excludeLayers; std::unordered_set<uint32_t> excludeLayerIds; ui::Dataspace dataspace; // Call this before holding mStateLock to avoid any deadlocking. Loading Loading @@ -6521,9 +6525,9 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY); for (const auto& handle : args.excludeHandles) { sp<Layer> excludeLayer = LayerHandle::getLayer(handle); if (excludeLayer != nullptr) { excludeLayers.emplace(excludeLayer); uint32_t excludeLayer = LayerHandle::getLayerId(handle); if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { ALOGW("Invalid layer handle passed as excludeLayer to captureLayers"); return NAME_NOT_FOUND; Loading Loading @@ -6552,7 +6556,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, args.captureSecureLayers); }); auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) { auto traverseLayers = [parent, args, excludeLayerIds](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { return; Loading @@ -6564,7 +6568,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, auto p = sp<Layer>::fromExisting(layer); while (p != nullptr) { if (excludeLayers.count(p) != 0) { if (excludeLayerIds.count(p->sequence) != 0) { return; } p = p->getParent(); Loading @@ -6573,20 +6577,21 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, visitor(layer); }); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); return BAD_VALUE; } auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); return fenceStatus(future.get()); } ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading @@ -6605,15 +6610,18 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { auto future = mScheduler->schedule([=]() { hasProtectedLayer = mScheduler ->schedule([=]() { bool protectedLayerFound = false; traverseLayers([&](Layer* layer) { protectedLayerFound = protectedLayerFound || (layer->isVisible() && layer->isProtected()); }); auto layers = getLayerSnapshots(); for (auto& [layer, layerFe] : layers) { protectedLayerFound |= (layerFe->mSnapshot->isVisible && layerFe->mSnapshot->hasProtectedContent); } return protectedLayerFound; }); hasProtectedLayer = future.get(); }) .get(); } const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | Loading @@ -6638,12 +6646,12 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), renderengine::impl::ExternalTexture::Usage:: WRITEABLE); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, return captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture, false /* regionSampling */, grayscale, captureListener); } ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading @@ -6666,7 +6674,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> renderFuture; renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { renderFuture = renderScreenImpl(renderArea, traverseLayers, buffer, renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, canCaptureBlackoutContent, regionSampling, grayscale, captureResults); }); Loading Loading @@ -6694,18 +6702,26 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( } ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( std::shared_ptr<const RenderArea> renderArea, TraverseLayersFunction traverseLayers, std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { ATRACE_CALL(); size_t layerCount = 0; traverseLayers([&](Layer* layer) { layerCount++; captureResults.capturedSecureLayers = captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); const auto& display = renderArea->getDisplayDevice(); const auto& transform = renderArea->getTransform(); std::unordered_set<compositionengine::LayerFE*> filterForScreenshot; auto layers = getLayerSnapshots(); for (auto& [layer, layerFE] : layers) { frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get(); captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure); captureResults.capturedHdrLayers |= isHdrLayer(*snapshot); layerFE->mSnapshot->geomLayerTransform = renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform; if (layer->needsFilteringForScreenshots(display.get(), transform)) { filterForScreenshot.insert(layerFE.get()); } } // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place Loading Loading @@ -6739,31 +6755,6 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( } captureResults.capturedDataspace = dataspace; const auto transform = renderArea->getTransform(); const auto display = renderArea->getDisplayDevice(); std::vector<std::pair<Layer*, sp<LayerFE>>> layers; layers.reserve(layerCount); std::unordered_set<compositionengine::LayerFE*> filterForScreenshot; traverseLayers([&](Layer* layer) { captureResults.capturedHdrLayers |= isHdrLayer(layer); // Layer::prepareClientComposition uses the layer's snapshot to populate the resulting // LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings are // generated with the layer's current buffer and geometry. layer->updateSnapshot(true /* updateGeometry */); layers.emplace_back(layer, layer->copyCompositionEngineLayerFE()); sp<LayerFE>& layerFE = layers.back().second; layerFE->mSnapshot->geomLayerTransform = renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform; if (layer->needsFilteringForScreenshots(display.get(), transform)) { filterForScreenshot.insert(layerFE.get()); } }); ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK}; if (!layers.empty()) { const sp<LayerFE>& layerFE = layers.back().second; Loading services/surfaceflinger/SurfaceFlinger.h +7 −5 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ #include "FlagManager.h" #include "FrontEnd/DisplayInfo.h" #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/LayerSnapshot.h" #include "FrontEnd/TransactionHandler.h" #include "LayerVector.h" #include "Scheduler/RefreshRateSelector.h" Loading Loading @@ -346,6 +347,7 @@ private: friend class LayerRenderArea; friend class LayerTracing; friend class SurfaceComposerAIDL; friend class DisplayRenderArea; // For unit tests friend class TestableSurfaceFlinger; Loading @@ -353,7 +355,7 @@ private: friend class TunnelModeEnabledReporterTest; using TransactionSchedule = scheduler::TransactionSchedule; using TraverseLayersFunction = std::function<void(const LayerVector::Visitor&)>; using GetLayerSnapshotsFunction = std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>; using RenderAreaFuture = ftl::Future<std::unique_ptr<RenderArea>>; using DumpArgs = Vector<String16>; using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>; Loading Loading @@ -787,16 +789,16 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); ftl::SharedFuture<FenceResult> captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ftl::SharedFuture<FenceResult> captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> captureScreenCommon( RenderAreaFuture, TraverseLayersFunction, RenderAreaFuture, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, TraverseLayersFunction, std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) REQUIRES(kMainThreadContext); Loading Loading @@ -1085,7 +1087,7 @@ private: void updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) REQUIRES(mStateLock, kMainThreadContext); bool isHdrLayer(Layer* layer) const; bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const; ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const REQUIRES(mStateLock); Loading services/surfaceflinger/tests/unittests/CompositionTest.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -238,6 +238,8 @@ void CompositionTest::captureScreenComposition() { CaptureArgs::UNSET_UID, visitor); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; mCaptureScreenBuffer = Loading @@ -246,7 +248,7 @@ void CompositionTest::captureScreenComposition() { HAL_PIXEL_FORMAT_RGBA_8888, 1, usage); auto future = mFlinger.renderScreenImpl(std::move(renderArea), traverseLayers, auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots, mCaptureScreenBuffer, forSystem, regionSampling); ASSERT_TRUE(future.valid()); const auto fenceResult = future.get(); Loading Loading
services/surfaceflinger/RegionSamplingThread.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -344,12 +344,13 @@ void RegionSamplingThread::captureSample() { renderengine::impl::ExternalTexture::Usage:: WRITEABLE); } auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); constexpr bool kRegionSampling = true; constexpr bool kGrayscale = false; if (const auto fenceResult = mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, mFlinger.captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, buffer, kRegionSampling, kGrayscale, nullptr) .get(); fenceResult.ok()) { Loading
services/surfaceflinger/RenderArea.h +15 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,21 @@ public: mRotationFlags(rotation), mLayerStackSpaceRect(layerStackRect) {} static std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> fromTraverseLayersLambda( std::function<void(const LayerVector::Visitor&)> traverseLayers) { return [traverseLayers = std::move(traverseLayers)]() { std::vector<std::pair<Layer*, sp<LayerFE>>> layers; traverseLayers([&](Layer* layer) { // Layer::prepareClientComposition uses the layer's snapshot to populate the // resulting LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings // are generated with the layer's current buffer and geometry. layer->updateSnapshot(true /* updateGeometry */); layers.emplace_back(layer, layer->copyCompositionEngineLayerFE()); }); return layers; }; } virtual ~RenderArea() = default; // Invoke drawLayers to render layers into the render area. Loading
services/surfaceflinger/SurfaceFlinger.cpp +56 −65 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ #include "FrameTracer/FrameTracer.h" #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/LayerHandle.h" #include "FrontEnd/LayerSnapshot.h" #include "HdrLayerInfoReporter.h" #include "Layer.h" #include "LayerProtoHelper.h" Loading Loading @@ -2515,30 +2516,30 @@ void SurfaceFlinger::updateLayerGeometry() { mLayersPendingRefresh.clear(); } bool SurfaceFlinger::isHdrLayer(Layer* layer) const { 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) { auto buffer = layer->getBuffer(); if (buffer && (buffer->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) { if (snapshot.externalTexture && (snapshot.externalTexture->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) { return false; } } if (isHdrDataspace(layer->getDataSpace())) { if (isHdrDataspace(snapshot.dataspace)) { return true; } // If the layer is not allowed to be dimmed, treat it as HDR. WindowManager may disable // dimming in order to keep animations invoking SDR screenshots of HDR layers seamless. // Treat such tagged layers as HDR so that DisplayManagerService does not try to change // the screen brightness if (!layer->isDimmingEnabled()) { if (!snapshot.dimmingEnabled) { return true; } // RANGE_EXTENDED layers may identify themselves as being "HDR" via a desired sdr/hdr ratio if ((layer->getDataSpace() & (int32_t)Dataspace::RANGE_MASK) == if ((snapshot.dataspace & (int32_t)Dataspace::RANGE_MASK) == (int32_t)Dataspace::RANGE_EXTENDED && layer->getDesiredSdrHdrRatio() > 1.01f) { snapshot.desiredSdrHdrRatio > 1.01f) { return true; } return false; Loading Loading @@ -2666,13 +2667,14 @@ void SurfaceFlinger::postComposition(nsecs_t callTime) { int32_t maxArea = 0; mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) { const auto layerFe = layer->getCompositionEngineLayerFE(); if (layer->isVisible() && compositionDisplay->includesLayer(layer->getOutputFilter())) { if (isHdrLayer(layer)) { const frontend::LayerSnapshot& snapshot = *layer->getLayerSnapshot(); if (snapshot.isVisible && compositionDisplay->includesLayer(snapshot.outputFilter)) { if (isHdrLayer(snapshot)) { const auto* outputLayer = compositionDisplay->getOutputLayerForLayer(layerFe); if (outputLayer) { info.mergeDesiredRatio(layer->getDesiredSdrHdrRatio()); info.mergeDesiredRatio(snapshot.desiredSdrHdrRatio); info.numberOfHdrLayers++; const auto displayFrame = outputLayer->getState().displayFrame; const int32_t area = displayFrame.width() * displayFrame.height(); Loading Loading @@ -6418,8 +6420,9 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, auto traverseLayers = [this, args, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, args.uid, visitor); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); return fenceStatus(future.get()); Loading Loading @@ -6454,6 +6457,7 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); Loading @@ -6463,7 +6467,7 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, constexpr bool kAllowProtected = false; constexpr bool kGrayscale = false; auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, captureListener); return fenceStatus(future.get()); Loading @@ -6481,7 +6485,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, ui::Size reqSize; sp<Layer> parent; Rect crop(args.sourceCrop); std::unordered_set<sp<Layer>, SpHash<Layer>> excludeLayers; std::unordered_set<uint32_t> excludeLayerIds; ui::Dataspace dataspace; // Call this before holding mStateLock to avoid any deadlocking. Loading Loading @@ -6521,9 +6525,9 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY); for (const auto& handle : args.excludeHandles) { sp<Layer> excludeLayer = LayerHandle::getLayer(handle); if (excludeLayer != nullptr) { excludeLayers.emplace(excludeLayer); uint32_t excludeLayer = LayerHandle::getLayerId(handle); if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { ALOGW("Invalid layer handle passed as excludeLayer to captureLayers"); return NAME_NOT_FOUND; Loading Loading @@ -6552,7 +6556,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, args.captureSecureLayers); }); auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) { auto traverseLayers = [parent, args, excludeLayerIds](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { return; Loading @@ -6564,7 +6568,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, auto p = sp<Layer>::fromExisting(layer); while (p != nullptr) { if (excludeLayers.count(p) != 0) { if (excludeLayerIds.count(p->sequence) != 0) { return; } p = p->getParent(); Loading @@ -6573,20 +6577,21 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, visitor(layer); }); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); return BAD_VALUE; } auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, auto future = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); return fenceStatus(future.get()); } ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading @@ -6605,15 +6610,18 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; if (allowProtected && supportsProtected) { auto future = mScheduler->schedule([=]() { hasProtectedLayer = mScheduler ->schedule([=]() { bool protectedLayerFound = false; traverseLayers([&](Layer* layer) { protectedLayerFound = protectedLayerFound || (layer->isVisible() && layer->isProtected()); }); auto layers = getLayerSnapshots(); for (auto& [layer, layerFe] : layers) { protectedLayerFound |= (layerFe->mSnapshot->isVisible && layerFe->mSnapshot->hasProtectedContent); } return protectedLayerFound; }); hasProtectedLayer = future.get(); }) .get(); } const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | Loading @@ -6638,12 +6646,12 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), renderengine::impl::ExternalTexture::Usage:: WRITEABLE); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, return captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture, false /* regionSampling */, grayscale, captureListener); } ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); Loading @@ -6666,7 +6674,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( ftl::SharedFuture<FenceResult> renderFuture; renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { renderFuture = renderScreenImpl(renderArea, traverseLayers, buffer, renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer, canCaptureBlackoutContent, regionSampling, grayscale, captureResults); }); Loading Loading @@ -6694,18 +6702,26 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( } ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( std::shared_ptr<const RenderArea> renderArea, TraverseLayersFunction traverseLayers, std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { ATRACE_CALL(); size_t layerCount = 0; traverseLayers([&](Layer* layer) { layerCount++; captureResults.capturedSecureLayers = captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); const auto& display = renderArea->getDisplayDevice(); const auto& transform = renderArea->getTransform(); std::unordered_set<compositionengine::LayerFE*> filterForScreenshot; auto layers = getLayerSnapshots(); for (auto& [layer, layerFE] : layers) { frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get(); captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure); captureResults.capturedHdrLayers |= isHdrLayer(*snapshot); layerFE->mSnapshot->geomLayerTransform = renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform; if (layer->needsFilteringForScreenshots(display.get(), transform)) { filterForScreenshot.insert(layerFE.get()); } } // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place Loading Loading @@ -6739,31 +6755,6 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( } captureResults.capturedDataspace = dataspace; const auto transform = renderArea->getTransform(); const auto display = renderArea->getDisplayDevice(); std::vector<std::pair<Layer*, sp<LayerFE>>> layers; layers.reserve(layerCount); std::unordered_set<compositionengine::LayerFE*> filterForScreenshot; traverseLayers([&](Layer* layer) { captureResults.capturedHdrLayers |= isHdrLayer(layer); // Layer::prepareClientComposition uses the layer's snapshot to populate the resulting // LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings are // generated with the layer's current buffer and geometry. layer->updateSnapshot(true /* updateGeometry */); layers.emplace_back(layer, layer->copyCompositionEngineLayerFE()); sp<LayerFE>& layerFE = layers.back().second; layerFE->mSnapshot->geomLayerTransform = renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform; if (layer->needsFilteringForScreenshots(display.get(), transform)) { filterForScreenshot.insert(layerFE.get()); } }); ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK}; if (!layers.empty()) { const sp<LayerFE>& layerFE = layers.back().second; Loading
services/surfaceflinger/SurfaceFlinger.h +7 −5 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ #include "FlagManager.h" #include "FrontEnd/DisplayInfo.h" #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/LayerSnapshot.h" #include "FrontEnd/TransactionHandler.h" #include "LayerVector.h" #include "Scheduler/RefreshRateSelector.h" Loading Loading @@ -346,6 +347,7 @@ private: friend class LayerRenderArea; friend class LayerTracing; friend class SurfaceComposerAIDL; friend class DisplayRenderArea; // For unit tests friend class TestableSurfaceFlinger; Loading @@ -353,7 +355,7 @@ private: friend class TunnelModeEnabledReporterTest; using TransactionSchedule = scheduler::TransactionSchedule; using TraverseLayersFunction = std::function<void(const LayerVector::Visitor&)>; using GetLayerSnapshotsFunction = std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>; using RenderAreaFuture = ftl::Future<std::unique_ptr<RenderArea>>; using DumpArgs = Vector<String16>; using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>; Loading Loading @@ -787,16 +789,16 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); ftl::SharedFuture<FenceResult> captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ftl::SharedFuture<FenceResult> captureScreenCommon(RenderAreaFuture, GetLayerSnapshotsFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> captureScreenCommon( RenderAreaFuture, TraverseLayersFunction, RenderAreaFuture, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling, bool grayscale, const sp<IScreenCaptureListener>&); ftl::SharedFuture<FenceResult> renderScreenImpl( std::shared_ptr<const RenderArea>, TraverseLayersFunction, std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction, const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock) REQUIRES(kMainThreadContext); Loading Loading @@ -1085,7 +1087,7 @@ private: void updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) REQUIRES(mStateLock, kMainThreadContext); bool isHdrLayer(Layer* layer) const; bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const; ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const REQUIRES(mStateLock); Loading
services/surfaceflinger/tests/unittests/CompositionTest.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -238,6 +238,8 @@ void CompositionTest::captureScreenComposition() { CaptureArgs::UNSET_UID, visitor); }; auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; mCaptureScreenBuffer = Loading @@ -246,7 +248,7 @@ void CompositionTest::captureScreenComposition() { HAL_PIXEL_FORMAT_RGBA_8888, 1, usage); auto future = mFlinger.renderScreenImpl(std::move(renderArea), traverseLayers, auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots, mCaptureScreenBuffer, forSystem, regionSampling); ASSERT_TRUE(future.valid()); const auto fenceResult = future.get(); Loading