Extensive handling of fixed rotation launching app

This fixes a case that display does not rotate after multiple
activities in a different rotation than display are launched.

- Link the transform state from the existing one to the new
  launching activity. So the heavy duplicated calculation is
  omitted and they can be recognized as a group to continue
  to update display rotation.
- Add a dedicated transition listener so it will not miss to
  handle display rotation if the reported token is different.
  That avoids leakage if somehow the transition is not notified
  then the listener is not unregistered. The path to finish
  fixed rotation is also simplified because there is always a
  transition listener to handle the incoming record.

Fixes: 154911677
Test: atest DisplayContentTests#testApplyTopFixedRotationTransform

Change-Id: Id370d7980d11553905b6a051482e3765ed61dc39
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 e02ea81..cba89d0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -790,9 +790,7 @@
         final DisplayContent dc = createNewDisplay();
         dc.getDisplayRotation().setFixedToUserRotation(
                 IWindowManager.FIXED_TO_USER_ROTATION_DISABLED);
-        final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
-                ? SCREEN_ORIENTATION_PORTRAIT
-                : SCREEN_ORIENTATION_LANDSCAPE;
+        final int newOrientation = getRotatedOrientation(dc);
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
@@ -812,9 +810,7 @@
         final DisplayContent dc = createNewDisplay();
         dc.getDisplayRotation().setFixedToUserRotation(
                 IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
-        final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
-                ? SCREEN_ORIENTATION_PORTRAIT
-                : SCREEN_ORIENTATION_LANDSCAPE;
+        final int newOrientation = getRotatedOrientation(dc);
 
         final ActivityStack stack =
                 new ActivityTestsBase.StackBuilder(mWm.mAtmService.mRootWindowContainer)
@@ -1083,7 +1079,8 @@
         mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */);
         mDisplayContent.mOpeningApps.add(app);
-        app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+        final int newOrientation = getRotatedOrientation(mDisplayContent);
+        app.setRequestedOrientation(newOrientation);
 
         assertTrue(app.isFixedRotationTransforming());
         assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
@@ -1124,12 +1121,25 @@
         mWallpaperWindow.mToken.onAnimationLeashCreated(t, null /* leash */);
         verify(t, never()).setPosition(any(), eq(0), eq(0));
 
+        // Launch another activity before the transition is finished.
+        final ActivityRecord app2 = new ActivityTestsBase.StackBuilder(mWm.mRoot)
+                .setDisplay(mDisplayContent).build().getTopMostActivity();
+        mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
+                false /* alwaysKeepCurrent */);
+        mDisplayContent.mOpeningApps.add(app2);
+        app2.setRequestedOrientation(newOrientation);
+
+        // The activity should share the same transform state as the existing one.
+        assertTrue(app.hasFixedRotationTransform(app2));
+
+        // The display should be rotated after the launch is finished.
         mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
 
         // The animation in old rotation should be cancelled.
         assertFalse(closingApp.isAnimating());
-        // The display should be rotated after the launch is finished.
+        // The fixed rotation should be cleared and the new rotation is applied to display.
         assertFalse(app.hasFixedRotationTransform());
+        assertFalse(app2.hasFixedRotationTransform());
         assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
     }
 
@@ -1292,6 +1302,12 @@
         assertThat("topToBottom", actualWindows, is(reverseList(expectedWindowsBottomToTop)));
     }
 
+    private static int getRotatedOrientation(DisplayContent dc) {
+        return dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
+                ? SCREEN_ORIENTATION_PORTRAIT
+                : SCREEN_ORIENTATION_LANDSCAPE;
+    }
+
     private static List<WindowState> reverseList(List<WindowState> list) {
         final ArrayList<WindowState> result = new ArrayList<>(list);
         Collections.reverse(result);