diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt index 4f665a860efe7..6c1c536d9e67e 100644 --- a/config/hiddenapi-vendor-list.txt +++ b/config/hiddenapi-vendor-list.txt @@ -20,7 +20,7 @@ Landroid/app/AppOpsManager$PackageOps;->getOps()Ljava/util/List; Landroid/app/AppOpsManager$PackageOps;->getPackageName()Ljava/lang/String; Landroid/app/AppOpsManager$PackageOps;->getUid()I Landroid/app/IActivityController$Stub;->()V -Landroid/app/IActivityManager;->cancelRecentsAnimation()V +Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo; diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index e1a02fa497f73..919f71472d333 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -450,7 +450,7 @@ interface IActivityManager { in Intent intent, in String resolvedType, in Bundle options, int userId); void startRecentsActivity(in Intent intent, in IAssistDataReceiver assistDataReceiver, in IRecentsAnimationRunner recentsAnimationRunner); - void cancelRecentsAnimation(); + void cancelRecentsAnimation(boolean restoreHomeStackPosition); int startActivityFromRecents(int taskId, in Bundle options); Bundle getActivityOptions(in IBinder token); List getAppTasks(in String callingPackage); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java index 1aad27f99cdce..6aa27542da9a0 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java @@ -258,9 +258,9 @@ public class ActivityManagerWrapper { /** * Cancels the remote recents animation started from {@link #startRecentsActivity}. */ - public void cancelRecentsAnimation() { + public void cancelRecentsAnimation(boolean restoreHomeStackPosition) { try { - ActivityManager.getService().cancelRecentsAnimation(); + ActivityManager.getService().cancelRecentsAnimation(restoreHomeStackPosition); } catch (RemoteException e) { Log.e(TAG, "Failed to cancel recents animation", e); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 44c27571fa3bf..1c9579d4c4abd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -52,6 +52,7 @@ import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonI import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.statusbar.VibratorHelper; +import static android.view.KeyEvent.KEYCODE_HOME; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; @@ -270,8 +271,12 @@ public class KeyButtonView extends ImageView implements ButtonInterface { if (mCode != 0) { if (doIt) { // If there was a pending remote recents animation, then we need to - // cancel the animation now before we handle the button itself - ActivityManagerWrapper.getInstance().cancelRecentsAnimation(); + // cancel the animation now before we handle the button itself. In the case + // where we are going home and the recents animation has already started, + // just cancel the recents animation, leaving the home stack in place + boolean isHomeKey = mCode == KEYCODE_HOME; + ActivityManagerWrapper.getInstance().cancelRecentsAnimation(!isHomeKey); + sendEvent(KeyEvent.ACTION_UP, 0); sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } else { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3ca89b4feb193..9330b4674d528 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -204,6 +204,8 @@ import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE; import static android.view.WindowManager.TRANSIT_TASK_OPEN; import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; +import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION; +import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_HOME_IN_PLACE; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.START_TAG; @@ -257,7 +259,6 @@ import android.app.WaitResult; import android.app.WindowConfiguration.ActivityType; import android.app.WindowConfiguration.WindowingMode; import android.app.admin.DevicePolicyCache; -import android.app.admin.DevicePolicyManager; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.app.backup.IBackupManager; @@ -5238,12 +5239,14 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void cancelRecentsAnimation() { + public void cancelRecentsAnimation(boolean restoreHomeStackPosition) { enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()"); final long origId = Binder.clearCallingIdentity(); try { synchronized (this) { - mWindowManager.cancelRecentsAnimation(); + mWindowManager.cancelRecentsAnimation(restoreHomeStackPosition + ? REORDER_MOVE_HOME_TO_ORIGINAL_POSITION + : REORDER_KEEP_HOME_IN_PLACE); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java index 9df321c64c9a8..5e74619be3834 100644 --- a/services/core/java/com/android/server/am/RecentsAnimation.java +++ b/services/core/java/com/android/server/am/RecentsAnimation.java @@ -23,6 +23,8 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.WindowManager.TRANSIT_NONE; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION; +import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_TOP; import android.app.ActivityOptions; import android.content.ComponentName; @@ -32,6 +34,7 @@ import android.os.RemoteException; import android.os.Trace; import android.util.Slog; import android.view.IRecentsAnimationRunner; +import com.android.server.wm.RecentsAnimationController; import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks; import com.android.server.wm.WindowManagerService; @@ -123,7 +126,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks { // Fetch all the surface controls and pass them to the client to get the animation // started - mWindowManager.cancelRecentsAnimation(); + mWindowManager.cancelRecentsAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this, display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds()); @@ -140,7 +143,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks { } @Override - public void onAnimationFinished(boolean moveHomeToTop) { + public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode) { synchronized (mService) { if (mWindowManager.getRecentsAnimationController() == null) return; @@ -151,9 +154,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks { "RecentsAnimation#onAnimationFinished_inSurfaceTransaction"); mWindowManager.deferSurfaceLayout(); try { - mWindowManager.cleanupRecentsAnimation(moveHomeToTop); + mWindowManager.cleanupRecentsAnimation(reorderMode); - // Move the home stack to the front final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity(); if (homeActivity == null) { return; @@ -162,15 +164,19 @@ class RecentsAnimation implements RecentsAnimationCallbacks { // Restore the launched-behind state homeActivity.mLaunchTaskBehind = false; - if (moveHomeToTop) { + if (reorderMode == REORDER_MOVE_HOME_TO_TOP) { // Bring the home stack to the front final ActivityStack homeStack = homeActivity.getStack(); mStackSupervisor.mNoAnimActivities.add(homeActivity); homeStack.moveToFront("RecentsAnimation.onAnimationFinished()"); - } else { + } else if (reorderMode == REORDER_MOVE_HOME_TO_ORIGINAL_POSITION){ // Restore the home stack to its previous position final ActivityDisplay display = homeActivity.getDisplay(); display.moveHomeStackBehindStack(mRestoreHomeBehindStack); + } else { + // Keep home stack in place, nothing changes, so ignore the transition logic + // below + return; } mWindowManager.prepareAppTransition(TRANSIT_NONE, false); diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index ba67ff6a678ec..112d93c750597 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -161,7 +161,10 @@ public class BoundsAnimationController { // Timeout callback to ensure we continue the animation if waiting for resuming or app // windows drawn fails - private final Runnable mResumeRunnable = () -> resume(); + private final Runnable mResumeRunnable = () -> { + if (DEBUG) Slog.d(TAG, "pause: timed out waiting for windows drawn"); + resume(); + }; BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState, @@ -213,7 +216,7 @@ public class BoundsAnimationController { // When starting an animation from fullscreen, pause here and wait for the // windows-drawn signal before we start the rest of the transition down into PiP. - if (mMoveFromFullscreen) { + if (mMoveFromFullscreen && mTarget.shouldDeferStartOnMoveToFullscreen()) { pause(); } } else if (mPrevSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END && diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java index 647a2d6deac62..68be4e8420a29 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java @@ -33,6 +33,12 @@ interface BoundsAnimationTarget { */ void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate); + /** + * @return Whether the animation should be paused waiting for the windows to draw before + * entering PiP. + */ + boolean shouldDeferStartOnMoveToFullscreen(); + /** * Sets the size of the target (without any intermediate steps, like scheduling animation) * but freezes the bounds of any tasks in the target at taskBounds, to allow for more diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 7274aee3c9872..29077f97ccdc6 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -29,6 +29,7 @@ import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; import static com.android.server.wm.AnimationAdapterProto.REMOTE; +import android.annotation.IntDef; import android.app.ActivityManager.TaskSnapshot; import android.app.WindowConfiguration; import android.graphics.Point; @@ -67,12 +68,25 @@ public class RecentsAnimationController implements DeathRecipient { private static final boolean DEBUG = false; private static final long FAILSAFE_DELAY = 1000; + public static final int REORDER_KEEP_HOME_IN_PLACE = 0; + public static final int REORDER_MOVE_HOME_TO_TOP = 1; + public static final int REORDER_MOVE_HOME_TO_ORIGINAL_POSITION = 2; + + @IntDef(prefix = { "REORDER_MODE_" }, value = { + REORDER_KEEP_HOME_IN_PLACE, + REORDER_MOVE_HOME_TO_TOP, + REORDER_MOVE_HOME_TO_ORIGINAL_POSITION + }) + public @interface ReorderMode {} + private final WindowManagerService mService; private final IRecentsAnimationRunner mRunner; private final RecentsAnimationCallbacks mCallbacks; private final ArrayList mPendingAnimations = new ArrayList<>(); private final int mDisplayId; - private final Runnable mFailsafeRunnable = this::cancelAnimation; + private final Runnable mFailsafeRunnable = () -> { + cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); + }; // The recents component app token that is shown behind the visibile tasks private AppWindowToken mHomeAppToken; @@ -93,7 +107,7 @@ public class RecentsAnimationController implements DeathRecipient { private Rect mTmpRect = new Rect(); public interface RecentsAnimationCallbacks { - void onAnimationFinished(boolean moveHomeToTop); + void onAnimationFinished(@ReorderMode int reorderMode); } private final IRecentsAnimationController mController = @@ -141,7 +155,9 @@ public class RecentsAnimationController implements DeathRecipient { // Note, the callback will handle its own synchronization, do not lock on WM lock // prior to calling the callback - mCallbacks.onAnimationFinished(moveHomeToTop); + mCallbacks.onAnimationFinished(moveHomeToTop + ? REORDER_MOVE_HOME_TO_TOP + : REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); } finally { Binder.restoreCallingIdentity(token); } @@ -222,14 +238,14 @@ public class RecentsAnimationController implements DeathRecipient { // Skip the animation if there is nothing to animate if (mPendingAnimations.isEmpty()) { - cancelAnimation(); + cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); return; } try { mRunner.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { - cancelAnimation(); + cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); return; } @@ -299,7 +315,7 @@ public class RecentsAnimationController implements DeathRecipient { reasons).sendToTarget(); } - void cancelAnimation() { + void cancelAnimation(@ReorderMode int reorderMode) { if (DEBUG) Log.d(TAG, "cancelAnimation()"); synchronized (mService.getWindowManagerLock()) { if (mCanceled) { @@ -316,16 +332,17 @@ public class RecentsAnimationController implements DeathRecipient { } // Clean up and return to the previous app // Don't hold the WM lock here as it calls back to AM/RecentsAnimation - mCallbacks.onAnimationFinished(false /* moveHomeToTop */); + mCallbacks.onAnimationFinished(reorderMode); } - void cleanupAnimation(boolean moveHomeToTop) { + void cleanupAnimation(@ReorderMode int reorderMode) { if (DEBUG) Log.d(TAG, "cleanupAnimation(): mPendingAnimations=" + mPendingAnimations.size()); for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { final TaskAnimationAdapter adapter = mPendingAnimations.get(i); adapter.mTask.setCanAffectSystemUiFlags(true); - if (moveHomeToTop) { + if (reorderMode == REORDER_MOVE_HOME_TO_TOP + || reorderMode == REORDER_KEEP_HOME_IN_PLACE) { adapter.mTask.dontAnimateDimExit(); } adapter.mCapturedFinishCallback.onAnimationFinished(adapter); @@ -344,7 +361,7 @@ public class RecentsAnimationController implements DeathRecipient { @Override public void binderDied() { - cancelAnimation(); + cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); } void checkAnimationReady(WallpaperController wallpaperController) { @@ -458,7 +475,7 @@ public class RecentsAnimationController implements DeathRecipient { @Override public void onAnimationCancelled(SurfaceControl animationLeash) { - cancelAnimation(); + cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); } @Override diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 62754ada7900d..c97f394b39b7a 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -33,8 +33,6 @@ import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; import static android.view.WindowManager.DOCKED_TOP; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; -import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS; import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME; import static com.android.server.wm.StackProto.ADJUST_DIVIDER_AMOUNT; @@ -47,6 +45,8 @@ import static com.android.server.wm.StackProto.ID; import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT; import static com.android.server.wm.StackProto.TASKS; import static com.android.server.wm.StackProto.WINDOW_CONTAINER; +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.CallSuper; import android.content.res.Configuration; @@ -62,12 +62,10 @@ import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; - import com.android.internal.policy.DividerSnapAlgorithm; import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; import com.android.internal.policy.DockedDividerUtils; import com.android.server.EventLogTags; - import java.io.PrintWriter; public class TaskStack extends WindowContainer implements @@ -1687,6 +1685,25 @@ public class TaskStack extends WindowContainer implements } } + @Override + public boolean shouldDeferStartOnMoveToFullscreen() { + // Workaround for the recents animation -- normally we need to wait for the new activity to + // show before starting the PiP animation, but because we start and show the home activity + // early for the recents animation prior to the PiP animation starting, there is no + // subsequent all-drawn signal. In this case, we can skip the pause when the home stack is + // already visible and drawn. + final TaskStack homeStack = mDisplayContent.getHomeStack(); + if (homeStack == null) { + return true; + } + final Task homeTask = homeStack.getTopChild(); + final AppWindowToken homeApp = homeTask.getTopVisibleAppToken(); + if (!homeTask.isVisible() || homeApp == null) { + return true; + } + return !homeApp.allDrawn; + } + /** * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen * bounds and we have a deferred PiP mode changed callback set with the animation. diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index c509980e1e9e2..6de1579292438 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -26,6 +26,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; +import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER; @@ -618,7 +619,8 @@ class WallpaperController { // If there was a recents animation in progress, cancel that animation if (mService.getRecentsAnimationController() != null) { - mService.getRecentsAnimationController().cancelAnimation(); + mService.getRecentsAnimationController().cancelAnimation( + REORDER_MOVE_HOME_TO_ORIGINAL_POSITION); } return true; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f1cd46bc16d01..28a57f5a46956 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2687,20 +2687,20 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void cancelRecentsAnimation() { + public void cancelRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode) { // Note: Do not hold the WM lock, this will lock appropriately in the call which also // calls through to AM/RecentsAnimation.onAnimationFinished() if (mRecentsAnimationController != null) { // This call will call through to cleanupAnimation() below after the animation is // canceled - mRecentsAnimationController.cancelAnimation(); + mRecentsAnimationController.cancelAnimation(reorderMode); } } - public void cleanupRecentsAnimation(boolean moveHomeToTop) { + public void cleanupRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode) { synchronized (mWindowMap) { if (mRecentsAnimationController != null) { - mRecentsAnimationController.cleanupAnimation(moveHomeToTop); + mRecentsAnimationController.cleanupAnimation(reorderMode); mRecentsAnimationController = null; mAppTransition.updateBooster(); } diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java index 77653872e5ee8..6290ff191847b 100644 --- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java +++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java @@ -649,7 +649,7 @@ public class RecentTasksTest extends ActivityTestsBase { assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0)); assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null, null)); - assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation()); + assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation(true)); } private void testGetTasksApis(boolean expectCallable) { diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java index 2bfe2742d419b..6019958d06501 100644 --- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java @@ -158,6 +158,11 @@ public class BoundsAnimationControllerTests extends WindowTestsBase { mForcePipModeChangedCallback = forceUpdate; } + @Override + public boolean shouldDeferStartOnMoveToFullscreen() { + return true; + } + @Override public boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds) { // TODO: Once we break the runs apart, we should fail() here if this is called outside