diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 01eb9c5cb3d9f..b545cf439879b 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3355,6 +3355,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final long origId = Binder.clearCallingIdentity(); try { + // Link the fixed rotation transform to this activity since we are transferring the + // starting window. + if (fromActivity.hasFixedRotationTransform()) { + mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(this, + false /* checkOpening */); + } + // Transfer the starting window over to the new token. mStartingData = fromActivity.mStartingData; startingSurface = fromActivity.startingSurface; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4e19a5224bb4f..78b28e4ebe658 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5671,7 +5671,11 @@ class DisplayContent extends WindowContainer { notifyFixedRotationTransform(true /* enabled */); } + /** + * Return {@code true} if one of the associated activity is still animating. Otherwise, + * return {@code false}. + */ + boolean hasAnimatingFixedRotationTransition() { + if (mFixedRotationTransformState == null) { + return false; + } + + for (int i = mFixedRotationTransformState.mAssociatedTokens.size() - 1; i >= 0; i--) { + final ActivityRecord r = + mFixedRotationTransformState.mAssociatedTokens.get(i).asActivityRecord(); + if (r != null && r.isAnimating(TRANSITION | PARENTS)) { + return true; + } + } + return false; + } + void finishFixedRotationTransform() { finishFixedRotationTransform(null /* applyDisplayRotation */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java index ef28a450695be..a16bd2a72a833 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java @@ -38,6 +38,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; @@ -452,6 +453,32 @@ public class AppWindowTokenTests extends WindowTestsBase { assertFalse(middle.isVisible()); } + @Test + public void testTransferStartingWindowSetFixedRotation() { + mWm.mIsFixedRotationTransformEnabled = true; + final ActivityRecord topActivity = createTestActivityRecordForGivenTask(mTask); + mTask.positionChildAt(topActivity, POSITION_TOP); + mActivity.addStartingWindow(mPackageName, + android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, + false); + waitUntilHandlersIdle(); + + // Make activities to have different rotation from it display and set fixed rotation + // transform to activity1. + int rotation = (mDisplayContent.getRotation() + 1) % 4; + mDisplayContent.setFixedRotationLaunchingApp(mActivity, rotation); + doReturn(rotation).when(mDisplayContent) + .rotationForActivityInDifferentOrientation(topActivity); + + // Make sure the fixed rotation transform linked to activity2 when adding starting window + // on activity2. + topActivity.addStartingWindow(mPackageName, + android.R.style.Theme, null, "Test", 0, 0, 0, 0, mActivity.appToken.asBinder(), + false, false, false, true, false); + waitUntilHandlersIdle(); + assertTrue(topActivity.hasFixedRotationTransform()); + } + private ActivityRecord createIsolatedTestActivityRecord() { final ActivityStack taskStack = createTaskStackOnDisplay(mDisplayContent); final Task task = createTaskInStack(taskStack, 0 /* userId */); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 4ad7dff870722..d3f677ced3294 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1144,7 +1144,14 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(app.hasFixedRotationTransform(app2)); assertTrue(mDisplayContent.isFixedRotationLaunchingApp(app2)); + // The fixed rotation transform can only be finished when all animation finished. + doReturn(false).when(app2).isAnimating(anyInt(), anyInt()); + mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app2.token); + assertTrue(app.hasFixedRotationTransform()); + assertTrue(app2.hasFixedRotationTransform()); + // The display should be rotated after the launch is finished. + doReturn(false).when(app).isAnimating(anyInt(), anyInt()); mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token); // The fixed rotation should be cleared and the new rotation is applied to display.