diff options
Diffstat (limited to 'libs')
2 files changed, 67 insertions, 8 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java index 521a65cc4df6..bfbddbbe4aa0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java @@ -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, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java index cbbb29199d75..b8f615a1855f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java @@ -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 |