Loading libs/gui/LayerState.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -919,6 +919,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { if (other.what & eLutsChanged) diff |= eLutsChanged; CHECK_DIFF(diff, ePictureProfileHandleChanged, other, pictureProfileHandle); CHECK_DIFF(diff, eAppContentPriorityChanged, other, appContentPriority); if (other.what & eStopLayerChanged) diff |= eStopLayerChanged; return diff; } Loading libs/gui/include/gui/LayerState.h +1 −0 Original line number Diff line number Diff line Loading @@ -254,6 +254,7 @@ struct layer_state_t { eClientDrawnCornerRadiusChanged = 0x200000'00000000, eBorderSettingsChanged = 0x400000'00000000, eBoxShadowSettingsChanged = 0x800000'00000000, eStopLayerChanged = 0x1000000'00000000, }; layer_state_t(); Loading services/surfaceflinger/FrontEnd/LayerCreationArgs.h +1 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ struct LayerCreationArgs { ui::LayerStack layerStackToMirror = ui::UNASSIGNED_LAYER_STACK; uint32_t parentId = UNASSIGNED_LAYER_ID; uint32_t layerIdToMirror = UNASSIGNED_LAYER_ID; uint32_t stopLayerId = UNASSIGNED_LAYER_ID; std::atomic<int32_t>* pendingBuffers = 0; }; Loading services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +100 −0 Original line number Diff line number Diff line Loading @@ -450,11 +450,17 @@ void LayerSnapshotBuilder::updateSnapshots(const Args& args) { LayerHierarchy::TraversalPath childPath = root.makeChild(args.root.getLayer()->id, LayerHierarchy::Variant::Attached); updateSnapshotsInHierarchy(args, args.root, childPath, rootSnapshot, /*depth=*/0); if (FlagManager::getInstance().stop_layer()) { applyStopLayers(args.root, childPath); } } else { for (auto& [childHierarchy, variant] : args.root.mChildren) { LayerHierarchy::TraversalPath childPath = root.makeChild(childHierarchy->getLayer()->id, variant); updateSnapshotsInHierarchy(args, *childHierarchy, childPath, rootSnapshot, /*depth=*/0); if (FlagManager::getInstance().stop_layer()) { applyStopLayers(*childHierarchy, childPath); } } } Loading Loading @@ -1397,4 +1403,98 @@ void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) { } } // Apply stop layers to the hierarchy. // // If layer X specifies stop layer Y, then any layer within X's subhierarchy that is z-ordered // above Y is hidden. The stop layer itself, layer Y, is also hidden. // // This works by traversing the hierarchy in z-order. When a layer that specifies a stop layer is // encountered, the specified stop layer is pushed to the stopLayer stack, the subhierarchy is // traversed, then the stop layer is popped from the stack. If a layer whose id is stored in the // stop layer stack is encountered during traversal, it is added to the activeStopLayers set. Any // layer visited while the activeStopLayer set is non-empty is hidden. When an element is popped // from the stopLayer stack, any active stop layers that are no longer in the stopLayer stack are // removed from the activeStopLayers set. void LayerSnapshotBuilder::applyStopLayers(const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath& traversalPath) { ftl::SmallVector<uint32_t, 5> stopLayers; ftl::SmallVector<uint32_t, 5> activeStopLayers; applyStopLayersInternal(hierarchy, traversalPath, stopLayers, activeStopLayers); } void LayerSnapshotBuilder::applyStopLayersInternal( const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath& traversalPath, ftl::SmallVector<uint32_t, 5>& stopLayers, ftl::SmallVector<uint32_t, 5>& activeStopLayers) { const RequestedLayerState* layer = hierarchy.getLayer(); // Push to the stopLayer stack. if (layer->stopLayerId != UNASSIGNED_LAYER_ID) { stopLayers.push_back(layer->stopLayerId); } // Hide this layer if the activeStopLayers set is non-empty. if (!activeStopLayers.empty()) { LayerSnapshot* snapshot = getSnapshot(traversalPath); snapshot->isHiddenByPolicyFromParent = true; } // Traverse z-ordered below children before potentially activating this layer as a stop layer. auto childIt = hierarchy.mChildren.begin(); while (childIt != hierarchy.mChildren.end()) { auto& [childHierarchy, childVariant] = *childIt; if (childHierarchy->getLayer()->z >= 0) { break; } childIt++; LayerHierarchy::TraversalPath childTraversalPath = traversalPath.makeChild(childHierarchy->getLayer()->id, childVariant); if (childTraversalPath.detached) { continue; } applyStopLayersInternal(*childHierarchy, childTraversalPath, stopLayers, activeStopLayers); } // Activate this layer as a stop layer if it's in the stopLayers stack. bool isStopLayer = std::find(stopLayers.begin(), stopLayers.end(), layer->id) != stopLayers.end(); if (isStopLayer) { activeStopLayers.push_back(layer->id); LayerSnapshot* snapshot = getSnapshot(traversalPath); snapshot->isHiddenByPolicyFromParent = true; } // Traverse z-ordered above children. while (childIt != hierarchy.mChildren.end()) { auto& [childHierarchy, childVariant] = *childIt++; LayerHierarchy::TraversalPath childTraversalPath = traversalPath.makeChild(childHierarchy->getLayer()->id, childVariant); if (childTraversalPath.detached) { continue; } applyStopLayersInternal(*childHierarchy, childTraversalPath, stopLayers, activeStopLayers); } // Pop from the stopLayer stack and remove active stop layers from the activeStopLayers set // if necessary. if (layer->stopLayerId != UNASSIGNED_LAYER_ID) { stopLayers.pop_back(); auto it = activeStopLayers.begin(); while (it != activeStopLayers.end()) { bool stopLayerNoLongerActive = std::find(stopLayers.begin(), stopLayers.end(), *it) == stopLayers.end(); if (stopLayerNoLongerActive) { activeStopLayers.unstable_erase(it); } else { it++; } } } } } // namespace android::surfaceflinger::frontend services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +5 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,11 @@ private: const Args& args, bool* outChildHasValidFrameRate); void updateTouchableRegionCrop(const Args& args); void applyStopLayers(const LayerHierarchy&, const LayerHierarchy::TraversalPath&); void applyStopLayersInternal(const LayerHierarchy&, const LayerHierarchy::TraversalPath&, ftl::SmallVector<uint32_t, 5>& stopLayers, ftl::SmallVector<uint32_t, 5>& activeStopLayers); std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*, LayerHierarchy::TraversalPathHash> mPathToSnapshot; Loading Loading
libs/gui/LayerState.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -919,6 +919,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { if (other.what & eLutsChanged) diff |= eLutsChanged; CHECK_DIFF(diff, ePictureProfileHandleChanged, other, pictureProfileHandle); CHECK_DIFF(diff, eAppContentPriorityChanged, other, appContentPriority); if (other.what & eStopLayerChanged) diff |= eStopLayerChanged; return diff; } Loading
libs/gui/include/gui/LayerState.h +1 −0 Original line number Diff line number Diff line Loading @@ -254,6 +254,7 @@ struct layer_state_t { eClientDrawnCornerRadiusChanged = 0x200000'00000000, eBorderSettingsChanged = 0x400000'00000000, eBoxShadowSettingsChanged = 0x800000'00000000, eStopLayerChanged = 0x1000000'00000000, }; layer_state_t(); Loading
services/surfaceflinger/FrontEnd/LayerCreationArgs.h +1 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ struct LayerCreationArgs { ui::LayerStack layerStackToMirror = ui::UNASSIGNED_LAYER_STACK; uint32_t parentId = UNASSIGNED_LAYER_ID; uint32_t layerIdToMirror = UNASSIGNED_LAYER_ID; uint32_t stopLayerId = UNASSIGNED_LAYER_ID; std::atomic<int32_t>* pendingBuffers = 0; }; Loading
services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +100 −0 Original line number Diff line number Diff line Loading @@ -450,11 +450,17 @@ void LayerSnapshotBuilder::updateSnapshots(const Args& args) { LayerHierarchy::TraversalPath childPath = root.makeChild(args.root.getLayer()->id, LayerHierarchy::Variant::Attached); updateSnapshotsInHierarchy(args, args.root, childPath, rootSnapshot, /*depth=*/0); if (FlagManager::getInstance().stop_layer()) { applyStopLayers(args.root, childPath); } } else { for (auto& [childHierarchy, variant] : args.root.mChildren) { LayerHierarchy::TraversalPath childPath = root.makeChild(childHierarchy->getLayer()->id, variant); updateSnapshotsInHierarchy(args, *childHierarchy, childPath, rootSnapshot, /*depth=*/0); if (FlagManager::getInstance().stop_layer()) { applyStopLayers(*childHierarchy, childPath); } } } Loading Loading @@ -1397,4 +1403,98 @@ void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) { } } // Apply stop layers to the hierarchy. // // If layer X specifies stop layer Y, then any layer within X's subhierarchy that is z-ordered // above Y is hidden. The stop layer itself, layer Y, is also hidden. // // This works by traversing the hierarchy in z-order. When a layer that specifies a stop layer is // encountered, the specified stop layer is pushed to the stopLayer stack, the subhierarchy is // traversed, then the stop layer is popped from the stack. If a layer whose id is stored in the // stop layer stack is encountered during traversal, it is added to the activeStopLayers set. Any // layer visited while the activeStopLayer set is non-empty is hidden. When an element is popped // from the stopLayer stack, any active stop layers that are no longer in the stopLayer stack are // removed from the activeStopLayers set. void LayerSnapshotBuilder::applyStopLayers(const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath& traversalPath) { ftl::SmallVector<uint32_t, 5> stopLayers; ftl::SmallVector<uint32_t, 5> activeStopLayers; applyStopLayersInternal(hierarchy, traversalPath, stopLayers, activeStopLayers); } void LayerSnapshotBuilder::applyStopLayersInternal( const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath& traversalPath, ftl::SmallVector<uint32_t, 5>& stopLayers, ftl::SmallVector<uint32_t, 5>& activeStopLayers) { const RequestedLayerState* layer = hierarchy.getLayer(); // Push to the stopLayer stack. if (layer->stopLayerId != UNASSIGNED_LAYER_ID) { stopLayers.push_back(layer->stopLayerId); } // Hide this layer if the activeStopLayers set is non-empty. if (!activeStopLayers.empty()) { LayerSnapshot* snapshot = getSnapshot(traversalPath); snapshot->isHiddenByPolicyFromParent = true; } // Traverse z-ordered below children before potentially activating this layer as a stop layer. auto childIt = hierarchy.mChildren.begin(); while (childIt != hierarchy.mChildren.end()) { auto& [childHierarchy, childVariant] = *childIt; if (childHierarchy->getLayer()->z >= 0) { break; } childIt++; LayerHierarchy::TraversalPath childTraversalPath = traversalPath.makeChild(childHierarchy->getLayer()->id, childVariant); if (childTraversalPath.detached) { continue; } applyStopLayersInternal(*childHierarchy, childTraversalPath, stopLayers, activeStopLayers); } // Activate this layer as a stop layer if it's in the stopLayers stack. bool isStopLayer = std::find(stopLayers.begin(), stopLayers.end(), layer->id) != stopLayers.end(); if (isStopLayer) { activeStopLayers.push_back(layer->id); LayerSnapshot* snapshot = getSnapshot(traversalPath); snapshot->isHiddenByPolicyFromParent = true; } // Traverse z-ordered above children. while (childIt != hierarchy.mChildren.end()) { auto& [childHierarchy, childVariant] = *childIt++; LayerHierarchy::TraversalPath childTraversalPath = traversalPath.makeChild(childHierarchy->getLayer()->id, childVariant); if (childTraversalPath.detached) { continue; } applyStopLayersInternal(*childHierarchy, childTraversalPath, stopLayers, activeStopLayers); } // Pop from the stopLayer stack and remove active stop layers from the activeStopLayers set // if necessary. if (layer->stopLayerId != UNASSIGNED_LAYER_ID) { stopLayers.pop_back(); auto it = activeStopLayers.begin(); while (it != activeStopLayers.end()) { bool stopLayerNoLongerActive = std::find(stopLayers.begin(), stopLayers.end(), *it) == stopLayers.end(); if (stopLayerNoLongerActive) { activeStopLayers.unstable_erase(it); } else { it++; } } } } } // namespace android::surfaceflinger::frontend
services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +5 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,11 @@ private: const Args& args, bool* outChildHasValidFrameRate); void updateTouchableRegionCrop(const Args& args); void applyStopLayers(const LayerHierarchy&, const LayerHierarchy::TraversalPath&); void applyStopLayersInternal(const LayerHierarchy&, const LayerHierarchy::TraversalPath&, ftl::SmallVector<uint32_t, 5>& stopLayers, ftl::SmallVector<uint32_t, 5>& activeStopLayers); std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*, LayerHierarchy::TraversalPathHash> mPathToSnapshot; Loading