Loading services/core/java/com/android/server/wm/ActivityRecord.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading services/core/java/com/android/server/wm/DisplayContent.java +5 −1 Original line number Diff line number Diff line Loading @@ -5671,7 +5671,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } if (mFixedRotationLaunchingApp != null && mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) { // Waiting until all of the associated activities have done animation, or the // orientation would be updated too early and cause flickers. if (!mFixedRotationLaunchingApp.hasAnimatingFixedRotationTransition()) { continueUpdateOrientationForDiffOrienLaunchingApp(); } } else { r.finishFixedRotationTransform(); } Loading services/core/java/com/android/server/wm/WindowToken.java +19 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,25 @@ class WindowToken extends WindowContainer<WindowState> { 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 */); } Loading services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */); Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +7 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
services/core/java/com/android/server/wm/DisplayContent.java +5 −1 Original line number Diff line number Diff line Loading @@ -5671,7 +5671,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } if (mFixedRotationLaunchingApp != null && mFixedRotationLaunchingApp.hasFixedRotationTransform(r)) { // Waiting until all of the associated activities have done animation, or the // orientation would be updated too early and cause flickers. if (!mFixedRotationLaunchingApp.hasAnimatingFixedRotationTransition()) { continueUpdateOrientationForDiffOrienLaunchingApp(); } } else { r.finishFixedRotationTransform(); } Loading
services/core/java/com/android/server/wm/WindowToken.java +19 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,25 @@ class WindowToken extends WindowContainer<WindowState> { 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 */); } Loading
services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */); Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +7 −0 Original line number Diff line number Diff line Loading @@ -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. Loading