diff options
3 files changed, 67 insertions, 11 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java index 4640106b5f1c..9b8006362c79 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java @@ -245,8 +245,8 @@ class ActivityEmbeddingAnimationSpec { private boolean shouldShowBackdrop(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change change) { - final Animation a = loadAttributeAnimation(info, change, WALLPAPER_TRANSITION_NONE, - mTransitionAnimation, false); + final Animation a = loadAttributeAnimation(info.getType(), info, change, + WALLPAPER_TRANSITION_NONE, mTransitionAnimation, false); return a != null && a.getShowBackdrop(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index 7df658e6c9db..d310ae32993c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -37,8 +37,12 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; import static android.view.WindowManager.TRANSIT_CHANGE; +import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; +import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_RELAUNCH; +import static android.view.WindowManager.TRANSIT_TO_FRONT; +import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL; @@ -334,6 +338,10 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { boolean isDisplayRotationAnimationStarted = false; final boolean isDreamTransition = isDreamTransition(info); final boolean isOnlyTranslucent = isOnlyTranslucent(info); + final boolean isActivityReplace = checkActivityReplacement(info, startTransaction); + // Some patterns (eg. activity "replacement") require us to re-interpret the type + @WindowManager.TransitionType final int transitType = + isActivityReplace ? TRANSIT_OPEN : info.getType(); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); @@ -430,7 +438,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { // Don't animate anything that isn't independent. if (!TransitionInfo.isIndependent(change, info)) continue; - Animation a = loadAnimation(info, change, wallpaperTransit, isDreamTransition); + Animation a = loadAnimation(transitType, info, change, wallpaperTransit, + isDreamTransition); if (a != null) { if (isTask) { final boolean isTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0; @@ -604,6 +613,53 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { return (translucentOpen + translucentClose) > 0; } + /** + * Checks for an edge-case where an activity calls finish() followed immediately by + * startActivity() to "replace" itself. If in this case, it will swap the layer of the + * close/open activities and return `true`. This way, we pretend like we are just "opening" + * the new activity. + */ + private static boolean checkActivityReplacement(@NonNull TransitionInfo info, + SurfaceControl.Transaction t) { + if (info.getType() != TRANSIT_CLOSE) { + return false; + } + int closing = -1; + int opening = -1; + for (int i = info.getChanges().size() - 1; i >= 0; --i) { + final TransitionInfo.Change change = info.getChanges().get(i); + if ((change.getTaskInfo() != null || change.hasFlags(FLAG_IS_DISPLAY)) + && !TransitionUtil.isOrderOnly(change)) { + // This isn't an activity-level transition. + return false; + } + if (change.getTaskInfo() != null + && change.hasFlags(FLAG_IS_DISPLAY | FLAGS_IS_NON_APP_WINDOW)) { + // Ignore non-activity containers. + continue; + } + if (TransitionUtil.isClosingType(change.getMode())) { + closing = i; + } else if (change.getMode() == TRANSIT_OPEN) { + // OPEN implies that it is a new launch. If going "back" the opening app will be + // TO_FRONT + opening = i; + } else if (change.getMode() == TRANSIT_TO_FRONT) { + // Normal "going back", so not a replacement. + return false; + } + } + if (closing < 0 || opening < 0) { + return false; + } + // Swap the opening and closing z-orders since we're swapping the transit type. + final int numChanges = info.getChanges().size(); + final int zSplitLine = numChanges + 1; + t.setLayer(info.getChanges().get(opening).getLeash(), zSplitLine + numChanges - opening); + t.setLayer(info.getChanges().get(closing).getLeash(), zSplitLine - closing); + return true; + } + @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @@ -656,12 +712,11 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } @Nullable - private Animation loadAnimation(@NonNull TransitionInfo info, + private Animation loadAnimation(int type, @NonNull TransitionInfo info, @NonNull TransitionInfo.Change change, int wallpaperTransit, boolean isDreamTransition) { Animation a; - final int type = info.getType(); final int flags = info.getFlags(); final int changeMode = change.getMode(); final int changeFlags = change.getFlags(); @@ -716,8 +771,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { // If there's a scene-transition, then jump-cut. return null; } else { - a = loadAttributeAnimation( - info, change, wallpaperTransit, mTransitionAnimation, isDreamTransition); + a = loadAttributeAnimation(type, info, change, wallpaperTransit, mTransitionAnimation, + isDreamTransition); } if (a != null) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java index d978eafa97f3..7b1ce2fe6a08 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java @@ -45,6 +45,7 @@ import android.graphics.Rect; import android.graphics.Shader; import android.view.Surface; import android.view.SurfaceControl; +import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.Transformation; import android.window.ScreenCapture; @@ -61,10 +62,10 @@ public class TransitionAnimationHelper { /** Loads the animation that is defined through attribute id for the given transition. */ @Nullable - public static Animation loadAttributeAnimation(@NonNull TransitionInfo info, - @NonNull TransitionInfo.Change change, int wallpaperTransit, - @NonNull TransitionAnimation transitionAnimation, boolean isDreamTransition) { - final int type = info.getType(); + public static Animation loadAttributeAnimation(@WindowManager.TransitionType int type, + @NonNull TransitionInfo info, @NonNull TransitionInfo.Change change, + int wallpaperTransit, @NonNull TransitionAnimation transitionAnimation, + boolean isDreamTransition) { final int changeMode = change.getMode(); final int changeFlags = change.getFlags(); final boolean enter = TransitionUtil.isOpeningType(changeMode); |