diff options
4 files changed, 46 insertions, 6 deletions
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index 35c959493f23..f2db5648a75f 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -269,6 +269,20 @@ public final class WindowContainerTransaction implements Parcelable { } /** + * Used in conjunction with a shell-transition call (usually finishTransition). This is + * basically a message to the transition system that a particular task should NOT go into + * PIP even though it normally would. This is to deal with some edge-case situations where + * Recents will "commit" the transition to go home, but then not actually go-home. + * @hide + */ + @NonNull + public WindowContainerTransaction setDoNotPip(@NonNull WindowContainerToken container) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mChangeMask |= Change.CHANGE_FORCE_NO_PIP; + return this; + } + + /** * Reparents a container into another one. The effect of a {@code null} parent can vary. For * example, reparenting a stack to {@code null} will reparent it to its display. * @@ -790,6 +804,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int CHANGE_HIDDEN = 1 << 3; public static final int CHANGE_BOUNDS_TRANSACTION_RECT = 1 << 4; public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 5; + public static final int CHANGE_FORCE_NO_PIP = 1 << 6; private final Configuration mConfiguration = new Configuration(); private boolean mFocusable = true; 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 b61827a0212c..51001a7a4c8e 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 @@ -331,13 +331,12 @@ public class RemoteTransitionCompat implements Parcelable { } if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint); final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - final WindowContainerTransaction wct; + final WindowContainerTransaction wct = new WindowContainerTransaction(); if (!toHome && mPausingTasks != null && mOpeningLeashes == null) { // The gesture went back to opening the app rather than continuing with // recents, so end the transition by moving the app back to the top (and also // re-showing it's task). - wct = new WindowContainerTransaction(); for (int i = mPausingTasks.size() - 1; i >= 0; --i) { // reverse order so that index 0 ends up on top wct.reorder(mPausingTasks.get(i), true /* onTop */); @@ -347,8 +346,14 @@ public class RemoteTransitionCompat implements Parcelable { wct.restoreTransientOrder(mRecentsTask); } } else { - wct = null; - if (mPipTask != null && mPipTransaction != null) { + if (!sendUserLeaveHint) { + for (int i = 0; i < mPausingTasks.size(); ++i) { + // This means recents is not *actually* finishing, so of course we gotta + // do special stuff in WMCore to accommodate. + wct.setDoNotPip(mPausingTasks.get(i)); + } + } + if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) { t.show(mInfo.getChange(mPipTask).getLeash()); PictureInPictureSurfaceTransaction.apply(mPipTransaction, mInfo.getChange(mPipTask).getLeash(), t); @@ -363,7 +368,7 @@ public class RemoteTransitionCompat implements Parcelable { t.remove(mLeashMap.valueAt(i)); } try { - mFinishCB.onTransitionFinished(wct, t); + mFinishCB.onTransitionFinished(wct.isEmpty() ? null : wct, t); } catch (RemoteException e) { Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e); t.apply(); diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index a0d68a1adb8a..973f98310d3e 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -189,6 +189,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe private boolean mNavBarAttachedToApp = false; private int mRecentsDisplayId = INVALID_DISPLAY; + /** @see #setCanPipOnFinish */ + private boolean mCanPipOnFinish = true; + Transition(@TransitionType int type, @TransitionFlags int flags, TransitionController controller, BLASTSyncEngine syncEngine) { mType = type; @@ -448,6 +451,15 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } /** + * Set whether this transition can start a pip-enter transition when finished. This is usually + * true, but gets set to false when recents decides that it wants to finish its animation but + * not actually finish its animation (yeah...). + */ + void setCanPipOnFinish(boolean canPipOnFinish) { + mCanPipOnFinish = canPipOnFinish; + } + + /** * The transition has finished animating and is ready to finalize WM state. This should not * be called directly; use {@link TransitionController#finishTransition} instead. */ @@ -475,7 +487,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // activity in a bad state. if (!visibleAtTransitionEnd && !ar.isVisibleRequested()) { boolean commitVisibility = true; - if (ar.isVisible() && ar.getTask() != null) { + if (mCanPipOnFinish && ar.isVisible() && ar.getTask() != null) { if (ar.pictureInPictureArgs != null && ar.pictureInPictureArgs.isAutoEnterEnabled()) { if (mTransientLaunches != null) { diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index fe5f6759a17a..3b1d2db0d1c7 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -426,6 +426,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } if (transition != null) transition.collect(wc); + if (finishTransition != null) { + // Deal with edge-cases in recents where it pretends to finish itself. + if ((entry.getValue().getChangeMask() + & WindowContainerTransaction.Change.CHANGE_FORCE_NO_PIP) != 0) { + finishTransition.setCanPipOnFinish(false /* canPipOnFinish */); + } + } + int containerEffect = applyWindowContainerChange(wc, entry.getValue()); effects |= containerEffect; |