Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fccd6362 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

[sf] destroy unreachable snapshots

Keep track of unreachable snapshots and destroy
them. This is a more robust way of cleaning up
snapshots rather than going through destroyed
layer handles. This way we will handle mirrored
snapshots when the original layer gets destroyed.

Test: presubmit
Bug: 238781169
Change-Id: Iddd5754ae71086719711ecaab218fc5f52e11ef5
parent 92990e29
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState {
    ui::Transform::RotationFlags fixedTransformHint;
    bool handleSkipScreenshotFlag = false;
    LayerHierarchy::TraversalPath mirrorRootPath;
    bool unreachable = true;
    ChildState childState;

    static bool isOpaqueFormat(PixelFormat format);
+15 −15
Original line number Diff line number Diff line
@@ -435,22 +435,18 @@ void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
        }
    }

    sortSnapshotsByZ(args);
    const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
    clearChanges(mRootSnapshot);

    // Destroy unreachable snapshots
    if (args.layerLifecycleManager.getDestroyedLayers().empty()) {
    if (!hasUnreachableSnapshots) {
        return;
    }

    std::unordered_set<uint32_t> destroyedLayerIds;
    for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
        destroyedLayerIds.emplace(destroyedLayer->id);
    }
    auto it = mSnapshots.begin();
    while (it < mSnapshots.end()) {
        auto& traversalPath = it->get()->path;
        if (destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
        if (!it->get()->unreachable) {
            it++;
            continue;
        }
@@ -534,18 +530,21 @@ LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::Traver
    return snapshot;
}

void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
    if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
        !args.layerLifecycleManager.getGlobalChanges().any(
                RequestedLayerState::Changes::Hierarchy |
                RequestedLayerState::Changes::Visibility)) {
        // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
        // the snapshots.
        return;
        return false;
    }

    mResortSnapshots = false;

    for (auto& snapshot : mSnapshots) {
        snapshot->unreachable = true;
    }

    size_t globalZ = 0;
    args.root.traverseInZOrder(
            [this, &globalZ](const LayerHierarchy&,
@@ -555,11 +554,7 @@ void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
                    return false;
                }

                if (snapshot->isHiddenByPolicy() &&
                    !snapshot->changes.test(RequestedLayerState::Changes::Visibility)) {
                    return false;
                }

                snapshot->unreachable = false;
                if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
                    updateVisibility(*snapshot, snapshot->getIsVisible());
                    size_t oldZ = snapshot->globalZ;
@@ -577,12 +572,17 @@ void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
                return true;
            });
    mNumInterestingSnapshots = (int)globalZ;
    bool hasUnreachableSnapshots = false;
    while (globalZ < mSnapshots.size()) {
        mSnapshots[globalZ]->globalZ = globalZ;
        /* mark unreachable snapshots as explicitly invisible */
        updateVisibility(*mSnapshots[globalZ], false);
        if (mSnapshots[globalZ]->unreachable) {
            hasUnreachableSnapshots = true;
        }
        globalZ++;
    }
    return hasUnreachableSnapshots;
}

void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
+2 −1
Original line number Diff line number Diff line
@@ -112,7 +112,8 @@ private:
    void updateInput(LayerSnapshot& snapshot, const RequestedLayerState& requested,
                     const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath& path,
                     const Args& args);
    void sortSnapshotsByZ(const Args& args);
    // Return true if there are unreachable snapshots
    bool sortSnapshotsByZ(const Args& args);
    LayerSnapshot* createSnapshot(const LayerHierarchy::TraversalPath& id,
                                  const RequestedLayerState& layer,
                                  const LayerSnapshot& parentSnapshot);
+31 −0
Original line number Diff line number Diff line
@@ -263,6 +263,37 @@ TEST_F(LayerHierarchyTest, relativeChildMovesOffscreenIsNotTraversable) {
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
}

TEST_F(LayerHierarchyTest, reparentRelativeLayer) {
    LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
    reparentRelativeLayer(11, 2);
    UPDATE_AND_VERIFY(hierarchyBuilder);

    std::vector<uint32_t> expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 11, 111};
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
    expectedTraversalPath = {1, 12, 121, 122, 1221, 13, 2, 11, 111};
    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
    expectedTraversalPath = {};
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);

    reparentLayer(11, 1);
    UPDATE_AND_VERIFY(hierarchyBuilder);
    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 11, 111};
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
    expectedTraversalPath = {1, 12, 121, 122, 1221, 13, 2, 11, 111};
    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
    expectedTraversalPath = {};
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);

    setZ(11, 0);
    UPDATE_AND_VERIFY(hierarchyBuilder);
    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2};
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
    expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2};
    EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
    expectedTraversalPath = {};
    EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
}

// mirror tests
TEST_F(LayerHierarchyTest, canTraverseMirrorLayer) {
    LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
+35 −0
Original line number Diff line number Diff line
@@ -391,4 +391,39 @@ TEST_F(LayerSnapshotTest, canRemoveDisplayMirror) {
    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
}

TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterMirroring) {
    size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
    createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
    setLayerStack(3, 1);
    std::vector<uint32_t> expected = {3, 1,  11,  111, 12,  121, 122,  1221, 13, 2,
                                      1, 11, 111, 12,  121, 122, 1221, 13,   2};
    UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
    destroyLayerHandle(3);
    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);

    EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size());
}

// Rel z doesn't create duplicate snapshots but this is for completeness
TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterRelZ) {
    size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
    reparentRelativeLayer(13, 11);
    UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 13, 111, 12, 121, 122, 1221, 2});
    setZ(13, 0);
    UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);

    EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size());
}

TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterLayerDestruction) {
    size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
    destroyLayerHandle(2);
    destroyLayerHandle(122);

    std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13};
    UPDATE_AND_VERIFY(mSnapshotBuilder, expected);

    EXPECT_LE(startingNumSnapshots - 2, mSnapshotBuilder.getSnapshots().size());
}

} // namespace android::surfaceflinger::frontend