From a7caedcbabb35443a7d7c0d0ef4aef6fa8f5af8e Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Sun, 26 Feb 2023 03:24:58 +0000 Subject: [sf] fix boot animation with new frontend We were dropping the transaction since it was passed via an internal function and not the transaction queue. Bug: 238781169 Test: boot animation Change-Id: I68818430eba08318bc2264d3a4b56150d92b0dc6 --- services/surfaceflinger/SurfaceFlinger.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bee89aa3ef..07b2fa153b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2268,12 +2268,13 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, LifecycleUpdate& upda mLayerLifecycleManager.commitChanges(); } + commitTransactions(); + // enter boot animation on first buffer latch if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) { ALOGI("Enter boot animation"); mBootStage = BootStage::BOOTANIMATION; } - commitTransactions(); } mustComposite |= (getTransactionFlags() & ~eTransactionFlushNeeded) || newDataLatched; return mustComposite; @@ -5207,8 +5208,18 @@ void SurfaceFlinger::onInitializeDisplays() { const sp token = display->getDisplayToken().promote(); LOG_ALWAYS_FATAL_IF(token == nullptr); + TransactionState state; + state.inputWindowCommands = mInputWindowCommands; + nsecs_t now = systemTime(); + state.desiredPresentTime = now; + state.postTime = now; + state.permissions = layer_state_t::ACCESS_SURFACE_FLINGER; + state.originPid = mPid; + state.originUid = static_cast(getuid()); + uint64_t transactionId = (((uint64_t)mPid) << 32) | mUniqueTransactionId++; + state.id = transactionId; + // reset screen orientation and use primary layer stack - std::vector state; Vector displays; DisplayState d; d.what = DisplayState::eDisplayProjectionChanged | @@ -5220,15 +5231,17 @@ void SurfaceFlinger::onInitializeDisplays() { d.layerStackSpaceRect.makeInvalid(); d.width = 0; d.height = 0; - displays.add(d); + state.displays.add(d); - nsecs_t now = systemTime(); + std::vector transactions; + transactions.emplace_back(state); - int64_t transactionId = (((int64_t)mPid) << 32) | mUniqueTransactionId++; // It should be on the main thread, apply it directly. - applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands, - /* desiredPresentTime */ now, true, {}, /* postTime */ now, true, false, - {}, mPid, getuid(), transactionId); + if (mLegacyFrontEndEnabled) { + applyTransactionsLocked(transactions, /*vsyncId=*/{0}); + } else { + applyAndCommitDisplayTransactionStates(transactions); + } setPowerModeInternal(display, hal::PowerMode::ON); } -- cgit v1.2.3-59-g8ed1b From ea6ff8192014357d3e720263bee60444e1f8f1d7 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 27 Feb 2023 17:41:39 +0000 Subject: [sf] write layer snapshots to layer trace Switch from using drawingstate to layer snapshots to generate layer trace if new front end is enabled. Test: atest FlickerTests Bug: 238781169 Change-Id: I9d75ee51ba77763db6fdd4c29f55e3fc498b683c --- .../surfaceflinger/FrontEnd/LayerHierarchy.cpp | 8 ++ services/surfaceflinger/FrontEnd/LayerHierarchy.h | 2 + services/surfaceflinger/Layer.cpp | 22 ++-- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/LayerProtoHelper.cpp | 146 +++++++++++++++++++++ services/surfaceflinger/LayerProtoHelper.h | 9 ++ services/surfaceflinger/SurfaceFlinger.cpp | 21 ++- 7 files changed, 196 insertions(+), 13 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 14d67c63a5..c30465fbd4 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -130,6 +130,14 @@ const RequestedLayerState* LayerHierarchy::getLayer() const { return mLayer; } +const LayerHierarchy* LayerHierarchy::getRelativeParent() const { + return mRelativeParent; +} + +const LayerHierarchy* LayerHierarchy::getParent() const { + return mParent; +} + std::string LayerHierarchy::getDebugStringShort() const { std::string debug = "LayerHierarchy{"; debug += ((mLayer) ? mLayer->getDebugString() : "root") + " "; diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index 0f700a9423..3dd89badff 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -144,6 +144,8 @@ public: } const RequestedLayerState* getLayer() const; + const LayerHierarchy* getRelativeParent() const; + const LayerHierarchy* getParent() const; std::string getDebugString(const char* prefix = "") const; std::string getDebugStringShort() const; // Traverse the hierarchy and return true if loops are found. The outInvalidRelativeRoot diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5ee701d617..d94f5ca52f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2097,15 +2097,7 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); if (traceFlags & LayerTracing::TRACE_COMPOSITION) { - ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread. - - // Only populate for the primary display. - if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) { - const auto compositionType = getCompositionType(*display); - layerProto->set_hwc_composition_type(static_cast(compositionType)); - LayerProtoHelper::writeToProto(getVisibleRegion(display.get()), - [&]() { return layerProto->mutable_visible_region(); }); - } + writeCompositionStateToProto(layerProto); } for (const sp& layer : mDrawingChildren) { @@ -2115,6 +2107,18 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { return layerProto; } +void Layer::writeCompositionStateToProto(LayerProto* layerProto) { + ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread. + + // Only populate for the primary display. + if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) { + const auto compositionType = getCompositionType(*display); + layerProto->set_hwc_composition_type(static_cast(compositionType)); + LayerProtoHelper::writeToProto(getVisibleRegion(display.get()), + [&]() { return layerProto->mutable_visible_region(); }); + } +} + void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { const ui::Transform transform = getTransform(); auto buffer = getExternalTexture(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9b7a4059ca..54f5fa74b9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -607,6 +607,7 @@ public: bool isRemovedFromCurrentState() const; LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags); + void writeCompositionStateToProto(LayerProto* layerProto); // 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 diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 0506c47555..1a828bf88c 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -247,6 +247,152 @@ void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegio outRegion.right = proto.right(); outRegion.bottom = proto.bottom(); } + +void LayerProtoHelper::writeHierarchyToProto( + LayersProto& outLayersProto, const frontend::LayerHierarchy& root, + const frontend::LayerSnapshotBuilder& snapshotBuilder, + const std::unordered_map>& legacyLayers, uint32_t traceFlags) { + using Variant = frontend::LayerHierarchy::Variant; + frontend::LayerSnapshot defaultSnapshot; + + LayerProto* layerProto = outLayersProto.add_layers(); + const frontend::RequestedLayerState& layer = *root.getLayer(); + frontend::LayerSnapshot* snapshot = snapshotBuilder.getSnapshot(layer.id); + + if (!snapshot) { + snapshot = &defaultSnapshot; + } + writeSnapshotToProto(layerProto, layer, *snapshot, traceFlags); + for (const auto& [child, variant] : root.mChildren) { + if (variant == Variant::Attached || variant == Variant::Detached) { + layerProto->add_children(child->getLayer()->id); + } else if (variant == Variant::Relative) { + layerProto->add_relatives(child->getLayer()->id); + } + } + + auto parent = root.getParent(); + if (parent && parent->getLayer()) { + layerProto->set_parent(parent->getLayer()->id); + } else { + layerProto->set_parent(-1); + } + + auto relativeParent = root.getRelativeParent(); + if (relativeParent && relativeParent->getLayer()) { + layerProto->set_z_order_relative_of(relativeParent->getLayer()->id); + } else { + layerProto->set_z_order_relative_of(-1); + } + + if (traceFlags & LayerTracing::TRACE_COMPOSITION) { + auto it = legacyLayers.find(layer.id); + if (it != legacyLayers.end()) { + it->second->writeCompositionStateToProto(layerProto); + } + } + + for (const auto& [child, variant] : root.mChildren) { + // avoid visiting relative layers twice + if (variant == Variant::Detached) { + continue; + } + writeHierarchyToProto(outLayersProto, *child, snapshotBuilder, legacyLayers, traceFlags); + } +} + +void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, + const frontend::RequestedLayerState& requestedState, + const frontend::LayerSnapshot& snapshot, + uint32_t traceFlags) { + const ui::Transform transform = snapshot.geomLayerTransform; + auto buffer = requestedState.externalTexture; + if (buffer != nullptr) { + LayerProtoHelper::writeToProto(*buffer, + [&]() { return layerInfo->mutable_active_buffer(); }); + LayerProtoHelper::writeToProtoDeprecated(ui::Transform(requestedState.bufferTransform), + layerInfo->mutable_buffer_transform()); + } + layerInfo->set_invalidate(snapshot.contentDirty); + layerInfo->set_is_protected(snapshot.hasProtectedContent); + layerInfo->set_dataspace(dataspaceDetails(static_cast(snapshot.dataspace))); + layerInfo->set_curr_frame(requestedState.bufferData->frameNumber); + layerInfo->set_requested_corner_radius(requestedState.cornerRadius); + layerInfo->set_corner_radius( + (snapshot.roundedCorner.radius.x + snapshot.roundedCorner.radius.y) / 2.0); + layerInfo->set_background_blur_radius(snapshot.backgroundBlurRadius); + layerInfo->set_is_trusted_overlay(snapshot.isTrustedOverlay); + LayerProtoHelper::writeToProtoDeprecated(transform, layerInfo->mutable_transform()); + LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), + [&]() { return layerInfo->mutable_position(); }); + LayerProtoHelper::writeToProto(snapshot.geomLayerBounds, + [&]() { return layerInfo->mutable_bounds(); }); + LayerProtoHelper::writeToProto(snapshot.surfaceDamage, + [&]() { return layerInfo->mutable_damage_region(); }); + + if (requestedState.hasColorTransform) { + LayerProtoHelper::writeToProto(snapshot.colorTransform, + layerInfo->mutable_color_transform()); + } + + LayerProtoHelper::writeToProto(snapshot.croppedBufferSize.toFloatRect(), + [&]() { return layerInfo->mutable_source_bounds(); }); + LayerProtoHelper::writeToProto(snapshot.transformedBounds, + [&]() { return layerInfo->mutable_screen_bounds(); }); + LayerProtoHelper::writeToProto(snapshot.roundedCorner.cropRect, + [&]() { return layerInfo->mutable_corner_radius_crop(); }); + layerInfo->set_shadow_radius(snapshot.shadowRadius); + + layerInfo->set_id(requestedState.id); + layerInfo->set_name(requestedState.name); + layerInfo->set_type("Layer"); + + LayerProtoHelper::writeToProto(requestedState.transparentRegion, + [&]() { return layerInfo->mutable_transparent_region(); }); + + layerInfo->set_layer_stack(snapshot.outputFilter.layerStack.id); + layerInfo->set_z(requestedState.z); + + ui::Transform requestedTransform = requestedState.getTransform(0); + LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(), [&]() { + return layerInfo->mutable_requested_position(); + }); + + LayerProtoHelper::writeToProto(requestedState.crop, + [&]() { return layerInfo->mutable_crop(); }); + + layerInfo->set_is_opaque(snapshot.contentOpaque); + if (requestedState.externalTexture) + layerInfo->set_pixel_format( + decodePixelFormat(requestedState.externalTexture->getPixelFormat())); + LayerProtoHelper::writeToProto(snapshot.color, [&]() { return layerInfo->mutable_color(); }); + LayerProtoHelper::writeToProto(requestedState.color, + [&]() { return layerInfo->mutable_requested_color(); }); + layerInfo->set_flags(requestedState.flags); + + LayerProtoHelper::writeToProtoDeprecated(requestedTransform, + layerInfo->mutable_requested_transform()); + + layerInfo->set_is_relative_of(requestedState.isRelativeOf); + + layerInfo->set_owner_uid(requestedState.ownerUid); + + if ((traceFlags & LayerTracing::TRACE_INPUT) && snapshot.hasInputInfo()) { + LayerProtoHelper::writeToProto(snapshot.inputInfo, {}, + [&]() { return layerInfo->mutable_input_window_info(); }); + } + + if (traceFlags & LayerTracing::TRACE_EXTRA) { + auto protoMap = layerInfo->mutable_metadata(); + for (const auto& entry : requestedState.metadata.mMap) { + (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend()); + } + } + + LayerProtoHelper::writeToProto(requestedState.destinationFrame, + [&]() { return layerInfo->mutable_destination_frame(); }); +} + } // namespace surfaceflinger } // namespace android diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h index 6ade1435e5..de4bd01f1a 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -58,6 +58,15 @@ public: 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 writeHierarchyToProto(LayersProto& layersProto, + const frontend::LayerHierarchy& root, + const frontend::LayerSnapshotBuilder& snapshotBuilder, + const std::unordered_map>& mLegacyLayers, + uint32_t traceFlags); + + static void writeSnapshotToProto(LayerProto* outProto, + const frontend::RequestedLayerState& requestedState, + const frontend::LayerSnapshot& snapshot, uint32_t traceFlags); }; } // namespace surfaceflinger diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 07b2fa153b..3882d0c106 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5680,14 +5680,27 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } } + if (mLegacyFrontEndEnabled) { + LayersProto layersProto; + for (const sp& layer : mDrawingState.layersSortedByZ) { + if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { + continue; + } + layer->writeToProto(layersProto, traceFlags); + } + return layersProto; + } + + const frontend::LayerHierarchy& root = mLayerHierarchyBuilder.getHierarchy(); LayersProto layersProto; - for (const sp& layer : mDrawingState.layersSortedByZ) { - if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { + for (auto& [child, variant] : root.mChildren) { + if (variant != frontend::LayerHierarchy::Variant::Attached || + stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) { continue; } - layer->writeToProto(layersProto, traceFlags); + LayerProtoHelper::writeHierarchyToProto(layersProto, *child, mLayerSnapshotBuilder, + mLegacyLayers, traceFlags); } - return layersProto; } -- cgit v1.2.3-59-g8ed1b From c5a5b6e0b3b8a14fb14e31985e6f533dd9f8edf7 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 28 Feb 2023 00:19:07 +0000 Subject: [sf] support region sampling with new frontend Use the new screenshot function but add support for a layer filter used by region sampling code. Test: check gesture nav bar color Test: atest libgui_test Bug: 238781169 Change-Id: I1c9370fd59b290fd1451d5c77cd27c275c685090 --- services/surfaceflinger/RegionSamplingThread.cpp | 97 +++++++++++++++--------- services/surfaceflinger/SurfaceFlinger.cpp | 22 ++++-- services/surfaceflinger/SurfaceFlinger.h | 4 +- 3 files changed, 81 insertions(+), 42 deletions(-) (limited to 'services/surfaceflinger/SurfaceFlinger.cpp') diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 839500f8a0..327ca3f0aa 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -285,47 +285,73 @@ void RegionSamplingThread::captureSample() { std::unordered_set, SpHash> listeners; - auto traverseLayers = [&](const LayerVector::Visitor& visitor) { - bool stopLayerFound = false; - auto filterVisitor = [&](Layer* layer) { - // We don't want to capture any layers beyond the stop layer - if (stopLayerFound) return; - - // Likewise if we just found a stop layer, set the flag and abort - for (const auto& [area, stopLayerId, listener] : descriptors) { - if (stopLayerId != UNASSIGNED_LAYER_ID && layer->getSequence() == stopLayerId) { - stopLayerFound = true; - return; - } + auto layerFilterFn = [&](const char* layerName, uint32_t layerId, const Rect& bounds, + const ui::Transform transform, bool& outStopTraversal) -> bool { + // Likewise if we just found a stop layer, set the flag and abort + for (const auto& [area, stopLayerId, listener] : descriptors) { + if (stopLayerId != UNASSIGNED_LAYER_ID && layerId == stopLayerId) { + outStopTraversal = true; + return false; } + } - // Compute the layer's position on the screen - const Rect bounds = Rect(layer->getBounds()); - const ui::Transform transform = layer->getTransform(); - constexpr bool roundOutwards = true; - Rect transformed = transform.transform(bounds, roundOutwards); - - // If this layer doesn't intersect with the larger sampledBounds, skip capturing it - Rect ignore; - if (!transformed.intersect(sampledBounds, &ignore)) return; - - // If the layer doesn't intersect a sampling area, skip capturing it - bool intersectsAnyArea = false; - for (const auto& [area, stopLayer, listener] : descriptors) { - if (transformed.intersect(area, &ignore)) { - intersectsAnyArea = true; - listeners.insert(listener); - } + // Compute the layer's position on the screen + constexpr bool roundOutwards = true; + Rect transformed = transform.transform(bounds, roundOutwards); + + // If this layer doesn't intersect with the larger sampledBounds, skip capturing it + Rect ignore; + if (!transformed.intersect(sampledBounds, &ignore)) return false; + + // If the layer doesn't intersect a sampling area, skip capturing it + bool intersectsAnyArea = false; + for (const auto& [area, stopLayer, listener] : descriptors) { + if (transformed.intersect(area, &ignore)) { + intersectsAnyArea = true; + listeners.insert(listener); } - if (!intersectsAnyArea) return; + } + if (!intersectsAnyArea) return false; - ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left, - bounds.top, bounds.right, bounds.bottom); - visitor(layer); - }; - mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor); + ALOGV("Traversing [%s] [%d, %d, %d, %d]", layerName, bounds.left, bounds.top, bounds.right, + bounds.bottom); + + return true; }; + std::function>>()> getLayerSnapshots; + if (mFlinger.mLayerLifecycleManagerEnabled) { + auto filterFn = [&](const frontend::LayerSnapshot& snapshot, + bool& outStopTraversal) -> bool { + const Rect bounds = + frontend::RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds), + snapshot.transparentRegionHint); + const ui::Transform transform = snapshot.geomLayerTransform; + return layerFilterFn(snapshot.name.c_str(), snapshot.path.id, bounds, transform, + outStopTraversal); + }; + getLayerSnapshots = + mFlinger.getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, + filterFn); + } else { + auto traverseLayers = [&](const LayerVector::Visitor& visitor) { + bool stopLayerFound = false; + auto filterVisitor = [&](Layer* layer) { + // We don't want to capture any layers beyond the stop layer + if (stopLayerFound) return; + + if (!layerFilterFn(layer->getDebugName(), layer->getSequence(), + Rect(layer->getBounds()), layer->getTransform(), + stopLayerFound)) { + return; + } + visitor(layer); + }; + mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor); + }; + getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); + } + std::shared_ptr buffer = nullptr; if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() && mCachedBuffer->getBuffer()->getHeight() == sampledBounds.getHeight()) { @@ -344,7 +370,6 @@ void RegionSamplingThread::captureSample() { renderengine::impl::ExternalTexture::Usage:: WRITEABLE); } - auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); constexpr bool kRegionSampling = true; constexpr bool kGrayscale = false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3882d0c106..b5b7b1e62e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6782,7 +6782,8 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, GetLayerSnapshotsFunction getLayerSnapshots; if (mLayerLifecycleManagerEnabled) { - getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, args.uid); + getLayerSnapshots = + getLayerSnapshotsForScreenshots(layerStack, args.uid, /*snapshotFilterFn=*/nullptr); } else { auto traverseLayers = [this, args, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, args.uid, visitor); @@ -6824,7 +6825,8 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, GetLayerSnapshotsFunction getLayerSnapshots; if (mLayerLifecycleManagerEnabled) { - getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID); + getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, + /*snapshotFilterFn=*/nullptr); } else { auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); @@ -7852,12 +7854,18 @@ std::vector> SurfaceFlinger::moveSnapshotsToComposit } std::function>>()> -SurfaceFlinger::getLayerSnapshotsForScreenshots(std::optional layerStack, - uint32_t uid) { +SurfaceFlinger::getLayerSnapshotsForScreenshots( + std::optional layerStack, uint32_t uid, + std::function + snapshotFilterFn) { return [&, layerStack, uid]() { std::vector>> layers; + bool stopTraversal = false; mLayerSnapshotBuilder.forEachVisibleSnapshot( [&](std::unique_ptr& snapshot) { + if (stopTraversal) { + return; + } if (layerStack && snapshot->outputFilter.layerStack != *layerStack) { return; } @@ -7867,6 +7875,9 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(std::optional la if (!snapshot->hasSomethingToDraw()) { return; } + if (snapshotFilterFn && !snapshotFilterFn(*snapshot, stopTraversal)) { + return; + } auto it = mLegacyLayers.find(snapshot->sequence); LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), @@ -7905,7 +7916,8 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t u .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()}; mLayerSnapshotBuilder.update(args); - auto getLayerSnapshotsFn = getLayerSnapshotsForScreenshots({}, uid); + auto getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots({}, uid, /*snapshotFilterFn=*/nullptr); std::vector>> layers = getLayerSnapshotsFn(); args.root = mLayerHierarchyBuilder.getHierarchy(); args.parentCrop.reset(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index adba9b86f9..ddb62325c5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1387,7 +1387,9 @@ private: [](const auto& display) { return display.isRefreshRateOverlayEnabled(); }); } std::function>>()> getLayerSnapshotsForScreenshots( - std::optional layerStack, uint32_t uid); + std::optional layerStack, uint32_t uid, + std::function + snapshotFilterFn); std::function>>()> getLayerSnapshotsForScreenshots( uint32_t rootLayerId, uint32_t uid, std::unordered_set excludeLayerIds, bool childrenOnly, const FloatRect& parentCrop); -- cgit v1.2.3-59-g8ed1b