diff options
7 files changed, 116 insertions, 65 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java index afc706ee9c8e..b8204d013105 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java @@ -19,6 +19,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM; import android.annotation.IntDef; @@ -55,4 +56,7 @@ public class SplitScreenConstants { {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED}; public static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE = {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW}; + + /** Flag applied to a transition change to identify it as a divider bar for animation. */ + public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index cfc193655f09..4bc8e913ec4e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -32,13 +32,13 @@ import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.view.WindowManager.transitTypeToString; -import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM; import static android.window.TransitionInfo.FLAG_IS_DISPLAY; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER; import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES; +import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED; @@ -147,9 +147,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private static final String TAG = StageCoordinator.class.getSimpleName(); - /** Flag applied to a transition change to identify it as a divider bar for animation. */ - public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM; - private final SurfaceSession mSurfaceSession = new SurfaceSession(); private final MainStage mMainStage; @@ -1809,7 +1806,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, boolean shouldAnimate = true; if (mSplitTransitions.isPendingEnter(transition)) { - shouldAnimate = startPendingEnterAnimation(transition, info, startTransaction); + shouldAnimate = startPendingEnterAnimation( + transition, info, startTransaction, finishTransaction); } else if (mSplitTransitions.isPendingRecent(transition)) { shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction); } else if (mSplitTransitions.isPendingDismiss(transition)) { @@ -1837,7 +1835,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private boolean startPendingEnterAnimation(@NonNull IBinder transition, - @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) { + @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, + @NonNull SurfaceControl.Transaction finishT) { // First, verify that we actually have opened apps in both splits. TransitionInfo.Change mainChild = null; TransitionInfo.Change sideChild = null; @@ -1884,8 +1883,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, + " before startAnimation()."); } - finishEnterSplitScreen(t); - addDividerBarToTransition(info, t, true /* show */); + finishEnterSplitScreen(finishT); + addDividerBarToTransition(info, finishT, true /* show */); return true; } @@ -1970,7 +1969,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return false; } - addDividerBarToTransition(info, t, false /* show */); + addDividerBarToTransition(info, finishT, false /* show */); return true; } @@ -1981,23 +1980,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } private void addDividerBarToTransition(@NonNull TransitionInfo info, - @NonNull SurfaceControl.Transaction t, boolean show) { + @NonNull SurfaceControl.Transaction finishT, boolean show) { final SurfaceControl leash = mSplitLayout.getDividerLeash(); final TransitionInfo.Change barChange = new TransitionInfo.Change(null /* token */, leash); - final Rect bounds = mSplitLayout.getDividerBounds(); - barChange.setStartAbsBounds(bounds); - barChange.setEndAbsBounds(bounds); + mSplitLayout.getRefDividerBounds(mTempRect1); + barChange.setStartAbsBounds(mTempRect1); + barChange.setEndAbsBounds(mTempRect1); barChange.setMode(show ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK); barChange.setFlags(FLAG_IS_DIVIDER_BAR); // Technically this should be order-0, but this is running after layer assignment // and it's a special case, so just add to end. info.addChange(barChange); - // Be default, make it visible. The remote animator can adjust alpha if it plans to animate. + if (show) { - t.setAlpha(leash, 1.f); - t.setLayer(leash, Integer.MAX_VALUE); - t.setPosition(leash, bounds.left, bounds.top); - t.show(leash); + finishT.setLayer(leash, Integer.MAX_VALUE); + finishT.setPosition(leash, mTempRect1.left, mTempRect1.top); + finishT.show(leash); + // Ensure divider surface are re-parented back into the hierarchy at the end of the + // transition. See Transition#buildFinishTransaction for more detail. + finishT.reparent(leash, mRootTaskLeash); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index 5cce6b99fb11..e26c259b2397 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -20,9 +20,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; +import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; -import static com.android.wm.shell.splitscreen.StageCoordinator.FLAG_IS_DIVIDER_BAR; import android.annotation.NonNull; import android.annotation.Nullable; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java index 9265f07ad284..33e8e3555eba 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java @@ -122,12 +122,13 @@ public class RemoteAnimationAdapterCompat { IRemoteTransitionFinishedCallback finishCallback) { final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>(); final RemoteAnimationTargetCompat[] appsCompat = - RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap); + RemoteAnimationTargetCompat.wrapApps(info, t, leashMap); final RemoteAnimationTargetCompat[] wallpapersCompat = - RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap); - // TODO(bc-unlock): Build wrapped object for non-apps target. + RemoteAnimationTargetCompat.wrapNonApps( + info, true /* wallpapers */, t, leashMap); final RemoteAnimationTargetCompat[] nonAppsCompat = - new RemoteAnimationTargetCompat[0]; + RemoteAnimationTargetCompat.wrapNonApps( + info, false /* wallpapers */, t, leashMap); // TODO(b/177438007): Move this set-up logic into launcher's animation impl. boolean isReturnToHome = false; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java index ef9e0951abf0..7c3b5fc52f0a 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java @@ -16,7 +16,9 @@ package com.android.systemui.shared.system; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; +import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; @@ -24,6 +26,8 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; +import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR; + import android.annotation.NonNull; import android.annotation.SuppressLint; import android.app.ActivityManager; @@ -76,7 +80,7 @@ public class RemoteAnimationTargetCompat { private final SurfaceControl mStartLeash; - // Fields used only to unrap into RemoteAnimationTarget + // Fields used only to unwrap into RemoteAnimationTarget private final Rect startBounds; public final boolean willShowImeOnTarget; @@ -203,8 +207,19 @@ public class RemoteAnimationTargetCompat { public RemoteAnimationTargetCompat(TransitionInfo.Change change, int order, TransitionInfo info, SurfaceControl.Transaction t) { - taskId = change.getTaskInfo() != null ? change.getTaskInfo().taskId : -1; mode = newModeToLegacyMode(change.getMode()); + taskInfo = change.getTaskInfo(); + if (taskInfo != null) { + taskId = taskInfo.taskId; + isNotInRecents = !taskInfo.isRunning; + activityType = taskInfo.getActivityType(); + windowConfiguration = taskInfo.configuration.windowConfiguration; + } else { + taskId = INVALID_TASK_ID; + isNotInRecents = true; + activityType = ACTIVITY_TYPE_UNDEFINED; + windowConfiguration = new WindowConfiguration(); + } // TODO: once we can properly sync transactions across process, then get rid of this leash. leash = createLeash(info, change, order, t); @@ -221,22 +236,12 @@ public class RemoteAnimationTargetCompat { prefixOrderIndex = order; // TODO(shell-transitions): I guess we need to send content insets? evaluate how its used. contentInsets = new Rect(0, 0, 0, 0); - if (change.getTaskInfo() != null) { - isNotInRecents = !change.getTaskInfo().isRunning; - activityType = change.getTaskInfo().getActivityType(); - } else { - isNotInRecents = true; - activityType = ACTIVITY_TYPE_UNDEFINED; - } - taskInfo = change.getTaskInfo(); allowEnterPip = change.getAllowEnterPip(); mStartLeash = null; rotationChange = change.getEndRotation() - change.getStartRotation(); - windowType = INVALID_WINDOW_TYPE; + windowType = (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0 + ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE; - windowConfiguration = change.getTaskInfo() != null - ? change.getTaskInfo().configuration.windowConfiguration - : new WindowConfiguration(); startBounds = change.getStartAbsBounds(); willShowImeOnTarget = (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0; } @@ -251,37 +256,62 @@ public class RemoteAnimationTargetCompat { } /** - * Represents a TransitionInfo object as an array of old-style targets + * Represents a TransitionInfo object as an array of old-style app targets + * + * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should be + * populated by this function. If null, it is ignored. + */ + public static RemoteAnimationTargetCompat[] wrapApps(TransitionInfo info, + SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) { + final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>(); + final SparseArray<TransitionInfo.Change> childTaskTargets = new SparseArray<>(); + for (int i = 0; i < info.getChanges().size(); i++) { + final TransitionInfo.Change change = info.getChanges().get(i); + if (change.getTaskInfo() == null) continue; + + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + // Children always come before parent since changes are in top-to-bottom z-order. + if (taskInfo != null) { + if (childTaskTargets.contains(taskInfo.taskId)) { + // has children, so not a leaf. Skip. + continue; + } + if (taskInfo.hasParentTask()) { + childTaskTargets.put(taskInfo.parentTaskId, change); + } + } + + final RemoteAnimationTargetCompat targetCompat = + new RemoteAnimationTargetCompat(change, info.getChanges().size() - i, info, t); + if (leashMap != null) { + leashMap.put(change.getLeash(), targetCompat.leash); + } + out.add(targetCompat); + } + + return out.toArray(new RemoteAnimationTargetCompat[out.size()]); + } + + /** + * Represents a TransitionInfo object as an array of old-style non-app targets * * @param wallpapers If true, this will return wallpaper targets; otherwise it returns * non-wallpaper targets. * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should be * populated by this function. If null, it is ignored. */ - public static RemoteAnimationTargetCompat[] wrap(TransitionInfo info, boolean wallpapers, + public static RemoteAnimationTargetCompat[] wrapNonApps(TransitionInfo info, boolean wallpapers, SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) { final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>(); - final SparseArray<TransitionInfo.Change> childTaskTargets = new SparseArray<>(); + for (int i = 0; i < info.getChanges().size(); i++) { final TransitionInfo.Change change = info.getChanges().get(i); + if (change.getTaskInfo() != null) continue; + final boolean changeIsWallpaper = (change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0; if (wallpapers != changeIsWallpaper) continue; - if (!wallpapers) { - final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); - // Children always come before parent since changes are in top-to-bottom z-order. - if (taskInfo != null) { - if (childTaskTargets.contains(taskInfo.taskId)) { - // has children, so not a leaf. Skip. - continue; - } - if (taskInfo.hasParentTask()) { - childTaskTargets.put(taskInfo.parentTaskId, change); - } - } - } - final RemoteAnimationTargetCompat targetCompat = new RemoteAnimationTargetCompat(change, info.getChanges().size() - i, info, t); if (leashMap != null) { diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index 7c1ef8c76926..f6792251d282 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -128,9 +128,10 @@ public class RemoteTransitionCompat implements Parcelable { IRemoteTransitionFinishedCallback finishedCallback) { final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>(); final RemoteAnimationTargetCompat[] apps = - RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap); + RemoteAnimationTargetCompat.wrapApps(info, t, leashMap); final RemoteAnimationTargetCompat[] wallpapers = - RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap); + RemoteAnimationTargetCompat.wrapNonApps( + info, true /* wallpapers */, t, leashMap); // TODO(b/177438007): Move this set-up logic into launcher's animation impl. mToken = transition; // This transition is for opening recents, so recents is on-top. We want to draw diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java index 360eef9d214f..cf5fa87272c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/system/RemoteTransitionTest.java @@ -19,12 +19,14 @@ package com.android.systemui.shared.system; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; +import static android.window.TransitionInfo.FLAG_FIRST_CUSTOM; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_STANDARD; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CHANGING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; @@ -64,12 +66,15 @@ public class RemoteTransitionTest extends SysuiTestCase { @Test public void testLegacyTargetExtract() { TransitionInfo combined = new TransitionInfoBuilder(TRANSIT_CLOSE) - .addChange(TRANSIT_CHANGE, FLAG_SHOW_WALLPAPER) - .addChange(TRANSIT_CLOSE, 0 /* flags */) - .addChange(TRANSIT_OPEN, FLAG_IS_WALLPAPER).build(); - // Check non-wallpaper extraction - RemoteAnimationTargetCompat[] wrapped = RemoteAnimationTargetCompat.wrap(combined, - false /* wallpapers */, mock(SurfaceControl.Transaction.class), null /* leashes */); + .addChange(TRANSIT_CHANGE, FLAG_SHOW_WALLPAPER, + createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_STANDARD)) + .addChange(TRANSIT_CLOSE, 0 /* flags */, + createTaskInfo(2 /* taskId */, ACTIVITY_TYPE_STANDARD)) + .addChange(TRANSIT_OPEN, FLAG_IS_WALLPAPER, null /* taskInfo */) + .addChange(TRANSIT_CHANGE, FLAG_FIRST_CUSTOM, null /* taskInfo */).build(); + // Check apps extraction + RemoteAnimationTargetCompat[] wrapped = RemoteAnimationTargetCompat.wrapApps(combined, + mock(SurfaceControl.Transaction.class), null /* leashes */); assertEquals(2, wrapped.length); int changeLayer = -1; int closeLayer = -1; @@ -86,17 +91,25 @@ public class RemoteTransitionTest extends SysuiTestCase { assertTrue(closeLayer < changeLayer); // Check wallpaper extraction - RemoteAnimationTargetCompat[] wallps = RemoteAnimationTargetCompat.wrap(combined, + RemoteAnimationTargetCompat[] wallps = RemoteAnimationTargetCompat.wrapNonApps(combined, true /* wallpapers */, mock(SurfaceControl.Transaction.class), null /* leashes */); assertEquals(1, wallps.length); assertTrue(wallps[0].prefixOrderIndex < closeLayer); assertEquals(MODE_OPENING, wallps[0].mode); + + // Check non-apps extraction + RemoteAnimationTargetCompat[] nonApps = RemoteAnimationTargetCompat.wrapNonApps(combined, + false /* wallpapers */, mock(SurfaceControl.Transaction.class), null /* leashes */); + assertEquals(1, nonApps.length); + assertTrue(nonApps[0].prefixOrderIndex < closeLayer); + assertEquals(MODE_CHANGING, nonApps[0].mode); } @Test public void testLegacyTargetWrapper() { TransitionInfo tinfo = new TransitionInfoBuilder(TRANSIT_CLOSE) - .addChange(TRANSIT_CHANGE, FLAG_TRANSLUCENT).build(); + .addChange(TRANSIT_CHANGE, FLAG_TRANSLUCENT, + createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_STANDARD)).build(); final TransitionInfo.Change change = tinfo.getChanges().get(0); final Rect endBounds = new Rect(40, 60, 140, 200); change.setTaskInfo(createTaskInfo(1 /* taskId */, ACTIVITY_TYPE_HOME)); @@ -119,11 +132,12 @@ public class RemoteTransitionTest extends SysuiTestCase { } TransitionInfoBuilder addChange(@WindowManager.TransitionType int mode, - @TransitionInfo.ChangeFlags int flags) { + @TransitionInfo.ChangeFlags int flags, ActivityManager.RunningTaskInfo taskInfo) { final TransitionInfo.Change change = new TransitionInfo.Change(null /* token */, createMockSurface(true)); change.setMode(mode); change.setFlags(flags); + change.setTaskInfo(taskInfo); mInfo.addChange(change); return this; } |