From c504ed49fd4930d746ee3e81e9090d0453f7e4fd Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Thu, 4 Mar 2021 12:47:23 -0800 Subject: [PATCH] Defer onTaskInfoChanged while transitioning to PiP The ApiDemos app triggers onTaskInfoChanged when transitioning from landscape to portrait PiP due to its implementation (fixed in a separate CL in same topic). Here we defer applying the TaskInfo received in onTaskInfoChanged till the entering transition finishes. Video: http://rcll/aaaaaabFQoRHlzixHdtY/c1n3cqwBydRxDrwxKHqI0H Bug: 180630127 Test: enter PiP w/ autoEnter from landscape in button navigation Test: atest WMShellUnitTests:com.android.wm.shell.pip.PipTaskOrganizerTest Change-Id: I3bc07dbb45a281d5c9b0bbfff7478e57b8944c60 --- .../wm/shell/pip/PipTaskOrganizer.java | 17 ++++++++++- .../wm/shell/pip/PipTaskOrganizerTest.java | 28 +++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 843e27f1b651c..7ed7fd0096bd9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -172,6 +172,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, }; private ActivityManager.RunningTaskInfo mTaskInfo; + // To handle the edge case that onTaskInfoChanged callback is received during the entering + // PiP transition, where we do not want to intercept the transition but still want to apply the + // changed RunningTaskInfo when it finishes. + private ActivityManager.RunningTaskInfo mDeferredTaskInfo; private WindowContainerToken mToken; private SurfaceControl mLeash; private State mState = State.UNDEFINED; @@ -520,12 +524,18 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPipTransitionController.sendOnPipTransitionStarted(direction); } - private void sendOnPipTransitionFinished( + @VisibleForTesting + void sendOnPipTransitionFinished( @PipAnimationController.TransitionDirection int direction) { if (direction == TRANSITION_DIRECTION_TO_PIP) { mState = State.ENTERED_PIP; } mPipTransitionController.sendOnPipTransitionFinished(direction); + // Apply the deferred RunningTaskInfo if applicable after all proper callbacks are sent. + if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) { + onTaskInfoChanged(mDeferredTaskInfo); + mDeferredTaskInfo = null; + } } private void sendOnPipTransitionCancelled( @@ -567,6 +577,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) { Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken"); + if (mState != State.ENTERED_PIP) { + Log.d(TAG, "Defer onTaskInfoChange in current state: " + mState); + mDeferredTaskInfo = info; + return; + } mPipBoundsState.setLastPipComponentName(info.topActivity); mPipBoundsState.setOverrideMinSize( mPipBoundsAlgorithm.getMinimalSize(info.topActivityInfo)); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index 79ec624a1557b..195b701a1c26b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -16,6 +16,8 @@ package com.android.wm.shell.pip; +import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; + import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -162,12 +164,30 @@ public class PipTaskOrganizerTest extends ShellTestCase { } @Test - public void onTaskInfoChanged_updatesAspectRatioIfChanged() { + public void onTaskInfoChanged_notInPip_deferUpdatesAspectRatio() { final Rational startAspectRatio = new Rational(2, 1); final Rational newAspectRatio = new Rational(1, 2); mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(startAspectRatio)), null /* leash */); + // It is in entering transition, should defer onTaskInfoChanged callback in this case. + mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, + createPipParams(newAspectRatio))); + assertEquals(startAspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f); + + // Once the entering transition finishes, the new aspect ratio applies in a deferred manner + mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + assertEquals(newAspectRatio.floatValue(), mPipBoundsState.getAspectRatio(), 0.01f); + } + + @Test + public void onTaskInfoChanged_inPip_updatesAspectRatioIfChanged() { + final Rational startAspectRatio = new Rational(2, 1); + final Rational newAspectRatio = new Rational(1, 2); + mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, + createPipParams(startAspectRatio)), null /* leash */); + mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent1, createPipParams(newAspectRatio))); @@ -175,9 +195,10 @@ public class PipTaskOrganizerTest extends ShellTestCase { } @Test - public void onTaskInfoChanged_updatesLastPipComponentName() { + public void onTaskInfoChanged_inPip_updatesLastPipComponentName() { mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), null /* leash */); + mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2, createPipParams(null))); @@ -186,9 +207,10 @@ public class PipTaskOrganizerTest extends ShellTestCase { } @Test - public void onTaskInfoChanged_updatesOverrideMinSize() { + public void onTaskInfoChanged_inPip_updatesOverrideMinSize() { mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1, createPipParams(null)), null /* leash */); + mSpiedPipTaskOrganizer.sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); final Size minSize = new Size(400, 320); mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,