From 11df410f7dcb8a2960a666ff57d83fc87bb90315 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Wed, 23 Mar 2022 15:52:26 -0700 Subject: [PATCH] Detect "expand to fullscreen" over recents and switch to it If a pip (or any other window) is expanded to fullscreen, it will occlude recents. In this situation, we should immediately finish the recents "animation" and let the new one play so we don't hang. This also adds a new "callback" for "replace with screenshot". We need this because if we just finish recents, it will immediately destroy the "live" tile. So this callback lets us replace the "live" tile with a screenshot beforehand. Bug: 223321653 Test: Put app in Pip, open another app, go to recents, expand pip Change-Id: I8a5ca05d5eef43e37c74f38b7988003bad7cdade --- .../system/RecentsAnimationListener.java | 10 ++++++++ .../shared/system/RemoteTransitionCompat.java | 23 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java index 48f1b76c1d503..5cca4a6a65f05 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java @@ -40,4 +40,14 @@ public interface RecentsAnimationListener { * was running becomes ready for control. */ void onTasksAppeared(RemoteAnimationTargetCompat[] app); + + /** + * Called to request that the current task tile be switched out for a screenshot (if not + * already). Once complete, onFinished should be called. + * @return true if this impl will call onFinished. No other onSwitchToScreenshot impls will + * be called afterwards (to avoid multiple calls to onFinished). + */ + default boolean onSwitchToScreenshot(Runnable onFinished) { + return false; + } } 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 b61827a0212c4..ff01e17d0cfd6 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 @@ -18,6 +18,7 @@ package com.android.systemui.shared.system; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_OPEN; @@ -244,6 +245,8 @@ public class RemoteTransitionCompat implements Parcelable { RecentsAnimationListener recents) { ArrayList openingTasks = null; boolean cancelRecents = false; + boolean homeGoingAway = false; + boolean hasChangingApp = false; for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) { @@ -257,8 +260,28 @@ public class RemoteTransitionCompat implements Parcelable { } openingTasks.add(change); } + } else if (change.getMode() == TRANSIT_CLOSE + || change.getMode() == TRANSIT_TO_BACK) { + if (mRecentsTask.equals(change.getContainer())) { + homeGoingAway = true; + } + } else if (change.getMode() == TRANSIT_CHANGE) { + hasChangingApp = true; } } + if (hasChangingApp && homeGoingAway) { + // This happens when a visible app is expanding (usually PiP). In this case, + // The transition probably has a special-purpose animation, so finish recents + // now and let it do its animation (since recents is going to be occluded). + if (!recents.onSwitchToScreenshot(() -> { + finish(true /* toHome */, false /* userLeaveHint */); + })) { + Log.w(TAG, "Recents callback doesn't support support switching to screenshot" + + ", there might be a flicker."); + finish(true /* toHome */, false /* userLeaveHint */); + } + return false; + } if (openingTasks == null) return false; int pauseMatches = 0; if (!cancelRecents) {