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

Commit 6073614a authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Accept occluded closing non-embedded change for embedded transition" into udc-dev

parents 1437e155 0dd47a2d
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static java.util.Objects.requireNonNull;

import android.content.Context;
import android.graphics.Rect;
import android.os.IBinder;
import android.util.ArrayMap;
import android.view.SurfaceControl;
@@ -35,6 +36,9 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.TransitionUtil;

import java.util.List;

/**
 * Responsible for handling ActivityEmbedding related transitions.
@@ -86,12 +90,13 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle
            @NonNull SurfaceControl.Transaction finishTransaction,
            @NonNull Transitions.TransitionFinishCallback finishCallback) {
        boolean containsEmbeddingSplit = false;
        for (TransitionInfo.Change change : info.getChanges()) {
        boolean containsNonEmbeddedChange = false;
        final List<TransitionInfo.Change> changes = info.getChanges();
        for (int i = changes.size() - 1; i >= 0; i--) {
            final TransitionInfo.Change change = changes.get(i);
            if (!change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) {
                // Only animate the transition if all changes are in a Task with ActivityEmbedding.
                return false;
            }
            if (!containsEmbeddingSplit && !change.hasFlags(FLAG_FILLS_TASK)) {
                containsNonEmbeddedChange = true;
            } else if (!change.hasFlags(FLAG_FILLS_TASK)) {
                // Whether the Task contains any ActivityEmbedding split before or after the
                // transition.
                containsEmbeddingSplit = true;
@@ -103,6 +108,9 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle
            // such as the device is in a folded state.
            return false;
        }
        if (containsNonEmbeddedChange && !handleNonEmbeddedChanges(changes)) {
            return false;
        }

        // Start ActivityEmbedding animation.
        mTransitionCallbacks.put(transition, finishCallback);
@@ -110,6 +118,37 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle
        return true;
    }

    private boolean handleNonEmbeddedChanges(List<TransitionInfo.Change> changes) {
        final Rect nonClosingEmbeddedArea = new Rect();
        for (int i = changes.size() - 1; i >= 0; i--) {
            final TransitionInfo.Change change = changes.get(i);
            if (!TransitionUtil.isClosingType(change.getMode())) {
                if (change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) {
                    nonClosingEmbeddedArea.union(change.getEndAbsBounds());
                    continue;
                }
                // Not able to handle non-embedded container if it is not closing.
                return false;
            }
        }
        for (int i = changes.size() - 1; i >= 0; i--) {
            final TransitionInfo.Change change = changes.get(i);
            if (!change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)
                    && !nonClosingEmbeddedArea.contains(change.getEndAbsBounds())) {
                // Unknown to animate containers outside the area of embedded activities.
                return false;
            }
        }
        // Drop the non-embedded closing change because it is occluded by embedded activities.
        for (int i = changes.size() - 1; i >= 0; i--) {
            final TransitionInfo.Change change = changes.get(i);
            if (!change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) {
                changes.remove(i);
            }
        }
        return true;
    }

    @Nullable
    @Override
    public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+23 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.activityembedding;

import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -82,10 +83,13 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation

    @Test
    public void testStartAnimation_containsNonActivityEmbeddingChange() {
        final TransitionInfo.Change nonEmbeddedOpen = createChange(0 /* flags */);
        final TransitionInfo.Change embeddedOpen = createEmbeddedChange(
                EMBEDDED_LEFT_BOUNDS, EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS);
        nonEmbeddedOpen.setMode(TRANSIT_OPEN);
        final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
                .addChange(createEmbeddedChange(
                        EMBEDDED_LEFT_BOUNDS, EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS))
                .addChange(createChange(0 /* flags */))
                .addChange(embeddedOpen)
                .addChange(nonEmbeddedOpen)
                .build();

        // No-op because it contains non-embedded change.
@@ -95,6 +99,22 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation
        verifyNoMoreInteractions(mStartTransaction);
        verifyNoMoreInteractions(mFinishTransaction);
        verifyNoMoreInteractions(mFinishCallback);

        final TransitionInfo.Change nonEmbeddedClose = createChange(0 /* flags */);
        nonEmbeddedClose.setMode(TRANSIT_CLOSE);
        nonEmbeddedClose.setEndAbsBounds(TASK_BOUNDS);
        final TransitionInfo.Change embeddedOpen2 = createEmbeddedChange(
                EMBEDDED_RIGHT_BOUNDS, EMBEDDED_RIGHT_BOUNDS, TASK_BOUNDS);
        final TransitionInfo info2 = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
                .addChange(embeddedOpen)
                .addChange(embeddedOpen2)
                .addChange(nonEmbeddedClose)
                .build();
        // Ok to animate because nonEmbeddedClose is occluded by embeddedOpen and embeddedOpen2.
        assertTrue(mController.startAnimation(mTransition, info2, mStartTransaction,
                mFinishTransaction, mFinishCallback));
        // The non-embedded change is dropped to avoid affecting embedded animation.
        assertFalse(info2.getChanges().contains(nonEmbeddedClose));
    }

    @Test
+1 −1
Original line number Diff line number Diff line
@@ -2835,7 +2835,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
            final String name = isDisplayRotation ? "RotationLayer" : "transition snapshot: " + wc;
            SurfaceControl snapshotSurface = wc.makeAnimationLeash()
                    .setName(name)
                    .setOpaque(true)
                    .setOpaque(wc.fillsParent())
                    .setParent(wc.getSurfaceControl())
                    .setSecure(screenshotBuffer.containsSecureLayers())
                    .setCallsite("Transition.ScreenshotSync")