From e65d74270d0098829735e44b21bb3203dc49bb60 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 25 Oct 2022 18:02:46 +0800 Subject: [PATCH] Exclude unnecessary animations of shell transition There may have multiple transitions when launching a task with embedded activities. In the last transition info, it may contain activities occluded by starting window and a closing wallpaper. By default, all of them will be animated with edge extension, that looks like showing some noise. Because the animation of embedded activities under a task level starting window is not visible, it can be skipped. But for non-embedded activity, the activity level starting window can be changed or closed with the host activity, so the case should not be skipped. Besides by default, wallpaper is no animation, especially it shouldn't apply any task/activity style animation. Also make sure the leash of starting window is always on top of the task with embedded activities. This just makes the surface hierarchy consistent. Bug: 255269113 Test: No flickering when cold launch Settings on a large screen device with support of activity embedded. Change-Id: I8fd1137e806aeb4060a83a71dc5aa02acdc42429 --- core/java/android/window/TransitionInfo.java | 11 ++++++++++- .../shell/transition/DefaultTransitionHandler.java | 12 ++++++++++++ .../core/java/com/android/server/wm/WindowState.java | 9 +++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index 8815ab35b6710..0956a71bd92d7 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -141,6 +141,10 @@ public final class TransitionInfo implements Parcelable { /** The first unused bit. This can be used by remotes to attach custom flags to this change. */ public static final int FLAG_FIRST_CUSTOM = 1 << 17; + /** The change belongs to a window that won't contain activities. */ + public static final int FLAGS_IS_NON_APP_WINDOW = + FLAG_IS_WALLPAPER | FLAG_IS_INPUT_METHOD | FLAG_IS_SYSTEM_WINDOW; + /** @hide */ @IntDef(prefix = { "FLAG_" }, value = { FLAG_NONE, @@ -579,11 +583,16 @@ public final class TransitionInfo implements Parcelable { return mFlags; } - /** Whether the given change flags has included in this change. */ + /** Whether this change contains any of the given change flags. */ public boolean hasFlags(@ChangeFlags int flags) { return (mFlags & flags) != 0; } + /** Whether this change contains all of the given change flags. */ + public boolean hasAllFlags(@ChangeFlags int flags) { + return (mFlags & flags) == flags; + } + /** * @return the bounds of the container before the change. It may be empty if the container * is coming into existence. 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 af79386caf9c4..928e71f8d3a6c 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 @@ -46,6 +46,7 @@ import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL; import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS; import static android.window.TransitionInfo.FLAG_FILLS_TASK; import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; +import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW; import static android.window.TransitionInfo.FLAG_IS_DISPLAY; import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; @@ -319,6 +320,17 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { final int wallpaperTransit = getWallpaperTransitType(info); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); + if (change.hasAllFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY + | FLAG_IS_BEHIND_STARTING_WINDOW)) { + // Don't animate embedded activity if it is covered by the starting window. + // Non-embedded case still needs animation because the container can still animate + // the starting window together, e.g. CLOSE or CHANGE type. + continue; + } + if (change.hasFlags(TransitionInfo.FLAGS_IS_NON_APP_WINDOW)) { + // Wallpaper, IME, and system windows don't need any default animations. + continue; + } final boolean isTask = change.getTaskInfo() != null; boolean isSeamlessDisplayChange = false; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c161a9b26f596..744bf0aa42d90 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5723,6 +5723,15 @@ class WindowState extends WindowContainer implements WindowManagerP return super.getAnimationLeashParent(); } + @Override + public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { + super.onAnimationLeashCreated(t, leash); + if (isStartingWindowAssociatedToTask()) { + // Make sure the animation leash is still on top of the task. + t.setLayer(leash, Integer.MAX_VALUE); + } + } + // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA // then we can drop all negative layering on the windowing side and simply inherit // the default implementation here.