summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2021-01-19 00:26:24 +0800
committer Riddle Hsu <riddlehsu@google.com> 2021-01-20 22:14:36 +0800
commita83c85c84242e01b892f44b5b28e16c2f22b326d (patch)
tree2ee02398b93c0146bc2841f94ddcb5524e380cae
parent1e465216e3ccd56215835c014b4d71f7e8598368 (diff)
Clear fixed rotation for app no longer changes rotation
For example: launch a landscape activity while device is portrait, and then launch another portrait activity before previous transition is done. If the landscape activity is destroyed before sending the fixed rotation adjustment for restoration, the adjustment is always retained by client side app. That causes the Display objects associated with application Resources always return rotation from the adjustment. This change clear the rotated state immediately when the top app has changed to the one that won't rotate the display. So the previous activity can receive the adjustment for restoration in time. Also simply a bit for the path of clearing fixed rotation state to avoid sending duplicated adjustments. Bug: 177390830 Test: DisplayContentTests#testClearIntermediateFixedRotation Change-Id: Ic13dff8b7a23a6022201a8fe7a981bb511b6e856
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java28
3 files changed, 39 insertions, 6 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 976924459252..99506067311d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1559,6 +1559,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
final int rotation = rotationForActivityInDifferentOrientation(r);
if (rotation == ROTATION_UNDEFINED) {
+ // The display rotation won't be changed by current top activity. If there was fixed
+ // rotation activity, its rotated state should be cleared to cancel the adjustments.
+ if (hasTopFixedRotationLaunchingApp()
+ // Avoid breaking recents animation.
+ && !mFixedRotationLaunchingApp.getTask().isAnimatingByRecents()) {
+ clearFixedRotationLaunchingApp();
+ }
return false;
}
if (!r.getParent().matchParentBounds()) {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 9e0fee3927c3..64e8184e793f 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -647,11 +647,6 @@ class WindowToken extends WindowContainer<WindowState> {
state.mIsTransforming = false;
if (applyDisplayRotation != null) {
applyDisplayRotation.run();
- } else {
- // The display will not rotate to the rotation of this container, let's cancel them.
- for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
- state.mAssociatedTokens.get(i).cancelFixedRotationTransform();
- }
}
// The state is cleared at the end, because it is used to indicate that other windows can
// use seamless rotation when applying rotation to display.
@@ -659,6 +654,10 @@ class WindowToken extends WindowContainer<WindowState> {
final WindowToken token = state.mAssociatedTokens.get(i);
token.mFixedRotationTransformState = null;
token.notifyFixedRotationTransform(false /* enabled */);
+ if (applyDisplayRotation == null) {
+ // Notify cancellation because the display does not change rotation.
+ token.cancelFixedRotationTransform();
+ }
}
}
@@ -707,7 +706,6 @@ class WindowToken extends WindowContainer<WindowState> {
// The window may be detached or detaching.
return;
}
- notifyFixedRotationTransform(false /* enabled */);
final int originalRotation = getWindowConfiguration().getRotation();
onConfigurationChanged(parent.getConfiguration());
onCancelFixedRotationTransform(originalRotation);
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 11be74d1a8c7..3db28a41d789 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -89,6 +89,7 @@ import static org.mockito.Mockito.doCallRealMethod;
import android.annotation.SuppressLint;
import android.app.ActivityTaskManager;
import android.app.WindowConfiguration;
+import android.app.servertransaction.FixedRotationAdjustmentsItem;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
@@ -1468,6 +1469,33 @@ public class DisplayContentTests extends WindowTestsBase {
}
@Test
+ public void testClearIntermediateFixedRotation() throws RemoteException {
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ mDisplayContent.setFixedRotationLaunchingApp(activity,
+ (mDisplayContent.getRotation() + 1) % 4);
+ // Create a window so FixedRotationAdjustmentsItem can be sent.
+ createWindow(null, TYPE_APPLICATION_STARTING, activity, "AppWin");
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ activity2.setVisible(false);
+ clearInvocations(mAtm.getLifecycleManager());
+ // The first activity has applied fixed rotation but the second activity becomes the top
+ // before the transition is done and it has the same rotation as display, so the dispatched
+ // rotation adjustment of first activity must be cleared.
+ mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(activity2,
+ false /* checkOpening */);
+
+ final ArgumentCaptor<FixedRotationAdjustmentsItem> adjustmentsCaptor =
+ ArgumentCaptor.forClass(FixedRotationAdjustmentsItem.class);
+ verify(mAtm.getLifecycleManager(), atLeastOnce()).scheduleTransaction(
+ eq(activity.app.getThread()), adjustmentsCaptor.capture());
+ assertFalse(activity.hasFixedRotationTransform());
+ final FixedRotationAdjustmentsItem clearAdjustments = FixedRotationAdjustmentsItem.obtain(
+ activity.token, null /* fixedRotationAdjustments */);
+ // The captor may match other items. The first one must be the item to clear adjustments.
+ assertEquals(clearAdjustments, adjustmentsCaptor.getAllValues().get(0));
+ }
+
+ @Test
public void testRemoteRotation() {
DisplayContent dc = createNewDisplay();