Fix letterbox and orientation request on DisplayAreaGroup

Before, with a multi displayarea policy setting, fixed-orientation app
may have incorrect bounds.

1. CompatDisplayInsets: use RootDisplayArea bounds as the mWidth and
   mHeight
2. onDescendantOrientationChanged: stop calling super method if ignore,
   otherwise it can return true from DC even though DAG is ignored. We
   want it to be hanled by Task in such case.
3. DAG should adjust the configuration orientation based on its
   dimensions, so a width > height DAG is considered landscape.
4. getRequestedConfigurationOrientation() should only reverse the
   orientation at DC level, so that Task and ActivityRecord can handle
   the bounds based on the request correctly.
5. Compare app bounds with RootDisplayArea bounds to check whether it
   is letterboxed.

Bug: 155431879
Test: manual: test with a dual displayarea policy
Test: atest WmTests:SizeCompatTests
Test: atest WmTests:DisplayAreaTest
Test: atest WmTests:DisplayAreaGroupTest
Change-Id: I16277cb9984c87ed4bcd50b91e0d12c2c6bbd5b1
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f65a5024..938f965 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7774,15 +7774,23 @@
                 return;
             }
 
-            if (container.getTask().isTaskLetterboxed()) {
+            final Task task = container.getTask();
+            if (task != null && task.isTaskLetterboxed()) {
                 // For apps in Task letterbox, it should fill the task bounds.
-                final Rect taskBounds = container.getTask().getBounds();
-                mWidth = taskBounds.width();
-                mHeight = taskBounds.height();
+                final Point dimensions = getRotationZeroDimensions(task);
+                mWidth = dimensions.x;
+                mHeight = dimensions.y;
             } else {
-                // If the activity is not floating nor letterboxed, assume it fills the display.
-                mWidth = display.mBaseDisplayWidth;
-                mHeight = display.mBaseDisplayHeight;
+                // If the activity is not floating nor letterboxed, assume it fills the root.
+                final RootDisplayArea root = container.getRootDisplayArea();
+                if (root == null || root == display) {
+                    mWidth = display.mBaseDisplayWidth;
+                    mHeight = display.mBaseDisplayHeight;
+                } else {
+                    final Point dimensions = getRotationZeroDimensions(root);
+                    mWidth = dimensions.x;
+                    mHeight = dimensions.y;
+                }
             }
             final DisplayPolicy policy = display.getDisplayPolicy();
             for (int rotation = 0; rotation < 4; rotation++) {
@@ -7799,6 +7807,20 @@
             }
         }
 
+        /**
+         * Gets the width and height of the {@code container} when it is not rotated, so that after
+         * the display is rotated, we can calculate the bounds by rotating the dimensions.
+         * @see #getBoundsByRotation
+         */
+        private static Point getRotationZeroDimensions(WindowContainer container) {
+            final Rect bounds = container.getBounds();
+            final int rotation = container.getConfiguration().windowConfiguration.getRotation();
+            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
+            final int width = bounds.width();
+            final int height = bounds.height();
+            return rotated ? new Point(height, width) : new Point(width, height);
+        }
+
         void getBoundsByRotation(Rect outBounds, int rotation) {
             final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
             final int dw = rotated ? mHeight : mWidth;
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index ce20dbd..8ad2958 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -33,6 +33,7 @@
 import android.annotation.Nullable;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.IBinder;
 import android.util.proto.ProtoOutputStream;
 import android.window.DisplayAreaInfo;
 import android.window.IDisplayAreaOrganizer;
@@ -149,6 +150,15 @@
         return !mIgnoreOrientationRequest && super.handlesOrientationChangeFromDescendant();
     }
 
+    @Override
+    boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
+            WindowContainer requestingContainer) {
+        // If this is set to ignore the orientation request, we don't propagate descendant
+        // orientation request.
+        return !mIgnoreOrientationRequest
+                && super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
+    }
+
     /**
      * Sets whether this {@link DisplayArea} should ignore fixed-orientation request from apps and
      * windows below it.
diff --git a/services/core/java/com/android/server/wm/DisplayAreaGroup.java b/services/core/java/com/android/server/wm/DisplayAreaGroup.java
index bcf8c7c..8488314 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaGroup.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaGroup.java
@@ -17,8 +17,12 @@
 package com.android.server.wm;
 
 import static android.content.pm.ActivityInfo.reverseOrientation;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 
 import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 
 /** The root of a partition of the logical display. */
@@ -30,13 +34,19 @@
 
     @Override
     boolean isOrientationDifferentFromDisplay() {
+        return isOrientationDifferentFromDisplay(getBounds());
+    }
+
+    /**
+     * Whether the orientation should be different from the {@link DisplayContent}.
+     * @param bounds the bounds of this DAG.
+     */
+    private boolean isOrientationDifferentFromDisplay(Rect bounds) {
         if (mDisplayContent == null) {
             return false;
         }
 
-        final Rect bounds = getBounds();
         final Rect displayBounds = mDisplayContent.getBounds();
-
         return (bounds.width() < bounds.height())
                 != (displayBounds.width() < displayBounds.height());
     }
@@ -54,4 +64,34 @@
         // display to be portrait, so that the DAG and the app will be in landscape.
         return isOrientationDifferentFromDisplay() ? reverseOrientation(orientation) : orientation;
     }
+
+    @Override
+    void resolveOverrideConfiguration(Configuration newParentConfiguration) {
+        super.resolveOverrideConfiguration(newParentConfiguration);
+        final Configuration resolvedConfig = getResolvedOverrideConfiguration();
+        if (resolvedConfig.orientation != ORIENTATION_UNDEFINED) {
+            // Don't change the orientation if it is requested on this window.
+            return;
+        }
+
+        // Use the override bounds because getBounds() may not be merged yet.
+        Rect overrideBounds = resolvedConfig.windowConfiguration.getBounds();
+        // It should fill parent if there is no override bounds.
+        overrideBounds = overrideBounds.isEmpty()
+                ? newParentConfiguration.windowConfiguration.getBounds()
+                : overrideBounds;
+        // Resolve the DAG orientation:
+        // If the orientation of this DAG should always be different from the display based on their
+        // dimensions, we need to reverse the config orientation.
+        // For example, if the display is 1200x900 (landscape), and this DAG is 600x900 (portrait).
+        // The orientation from the Display will be landscape, but we want to reverse it to be
+        // portrait for the DAG and its children.
+        if (isOrientationDifferentFromDisplay(overrideBounds)) {
+            if (newParentConfiguration.orientation == ORIENTATION_PORTRAIT) {
+                resolvedConfig.orientation = ORIENTATION_LANDSCAPE;
+            } else if (newParentConfiguration.orientation == ORIENTATION_LANDSCAPE) {
+                resolvedConfig.orientation = ORIENTATION_PORTRAIT;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6453ddf..439fe88 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1430,8 +1430,8 @@
         if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
             return ROTATION_UNDEFINED;
         }
-        if (r.inMultiWindowMode()
-                || r.getRequestedConfigurationOrientation() == getConfiguration().orientation) {
+        if (r.inMultiWindowMode() || r.getRequestedConfigurationOrientation(true /* forDisplay */)
+                == getConfiguration().orientation) {
             return ROTATION_UNDEFINED;
         }
         final int currentRotation = getRotation();
@@ -5496,7 +5496,7 @@
          */
         boolean isTopFixedOrientationRecentsAnimating() {
             return mAnimatingRecents != null
-                    && mAnimatingRecents.getRequestedConfigurationOrientation()
+                    && mAnimatingRecents.getRequestedConfigurationOrientation(true /* forDisplay */)
                     != ORIENTATION_UNDEFINED && !hasTopFixedRotationLaunchingApp();
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 0f6b62b..5246db0 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1169,7 +1169,7 @@
     }
 
     /**
-     * Get the configuration orientation by the requested screen orientation
+     * Gets the configuration orientation by the requested screen orientation
      * ({@link ActivityInfo.ScreenOrientation}) of this activity.
      *
      * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
@@ -1177,9 +1177,26 @@
      *         {@link Configuration#ORIENTATION_UNDEFINED}).
      */
     int getRequestedConfigurationOrientation() {
+        return getRequestedConfigurationOrientation(false /* forDisplay */);
+    }
+
+    /**
+     * Gets the configuration orientation by the requested screen orientation
+     * ({@link ActivityInfo.ScreenOrientation}) of this activity.
+     *
+     * @param forDisplay whether it is the requested config orientation for display.
+     *                   If {@code true}, we may reverse the requested orientation if the root is
+     *                   different from the display, so that when the display rotates to the
+     *                   reversed orientation, the requested app will be in the requested
+     *                   orientation.
+     * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
+     *         {@link Configuration#ORIENTATION_PORTRAIT},
+     *         {@link Configuration#ORIENTATION_UNDEFINED}).
+     */
+    int getRequestedConfigurationOrientation(boolean forDisplay) {
         int requestedOrientation = mOrientation;
         final RootDisplayArea root = getRootDisplayArea();
-        if (root != null && root.isOrientationDifferentFromDisplay()) {
+        if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
             // Reverse the requested orientation if the orientation of its root is different from
             // the display, so that when the display rotates to the reversed orientation, the
             // requested app will be in the requested orientation.
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9234390..90da36f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2126,6 +2126,14 @@
         return getDisplayContent().getBounds().equals(getBounds());
     }
 
+    private boolean matchesRootDisplayAreaBounds() {
+        RootDisplayArea root = getRootDisplayArea();
+        if (root == null || root == getDisplayContent()) {
+            return matchesDisplayBounds();
+        }
+        return root.getBounds().equals(getBounds());
+    }
+
     /**
      * @return {@code true} if last applied config was reported to the client already, {@code false}
      *         otherwise.
@@ -3780,7 +3788,7 @@
     /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or
      *          is transitioning into/out-of fullscreen. */
     boolean isLetterboxedAppWindow() {
-        return !inMultiWindowMode() && !matchesDisplayBounds()
+        return !inMultiWindowMode() && !matchesRootDisplayAreaBounds()
                 || isLetterboxedForDisplayCutout();
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
index 4a5a81e8..cfe956f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
@@ -90,7 +90,7 @@
     }
 
     @Test
-    public void testGetOrientation() {
+    public void testGetRequestedOrientationForDisplay() {
         doReturn(true).when(mDisplayContent).onDescendantOrientationChanged(any(), any());
         mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
@@ -98,21 +98,44 @@
         mDisplayContent.setBounds(0, 0, 600, 900);
 
         assertThat(mDisplayAreaGroup.getOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
-        assertThat(mActivity.getRequestedConfigurationOrientation())
+        assertThat(mActivity.getRequestedConfigurationOrientation(true /* forDisplay */))
                 .isEqualTo(ORIENTATION_PORTRAIT);
 
         // DisplayAreaGroup is landscape, different from Display
         mDisplayAreaGroup.setBounds(0, 0, 600, 450);
 
         assertThat(mDisplayAreaGroup.getOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
-        assertThat(mActivity.getRequestedConfigurationOrientation())
+        assertThat(mActivity.getRequestedConfigurationOrientation(true /* forDisplay */))
                 .isEqualTo(ORIENTATION_LANDSCAPE);
 
         // DisplayAreaGroup is portrait, same as Display
         mDisplayAreaGroup.setBounds(0, 0, 300, 900);
 
         assertThat(mDisplayAreaGroup.getOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
-        assertThat(mActivity.getRequestedConfigurationOrientation())
+        assertThat(mActivity.getRequestedConfigurationOrientation(true /* forDisplay */))
+                .isEqualTo(ORIENTATION_PORTRAIT);
+    }
+
+    @Test
+    public void testResolveOverrideConfiguration_reverseOrientationWhenDifferentFromParentRoot() {
+        mDisplayContent.setBounds(0, 0, 600, 900);
+        mDisplayContent.updateOrientation();
+        mDisplayContent.sendNewConfiguration();
+
+        // DAG fills Display
+        assertThat(mDisplayAreaGroup.getConfiguration().orientation)
+                .isEqualTo(ORIENTATION_PORTRAIT);
+
+        // DisplayAreaGroup is landscape, different from Display
+        mDisplayAreaGroup.setBounds(0, 0, 600, 450);
+
+        assertThat(mDisplayAreaGroup.getConfiguration().orientation)
+                .isEqualTo(ORIENTATION_LANDSCAPE);
+
+        // DisplayAreaGroup is portriat, same as Display
+        mDisplayAreaGroup.setBounds(0, 0, 300, 450);
+
+        assertThat(mDisplayAreaGroup.getConfiguration().orientation)
                 .isEqualTo(ORIENTATION_PORTRAIT);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index 01c1f1f..04adcd6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import static android.content.ActivityInfoProto.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
@@ -25,7 +27,9 @@
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
 import static com.android.server.wm.DisplayArea.Type.ANY;
 import static com.android.server.wm.DisplayArea.Type.BELOW_TASKS;
@@ -41,6 +45,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
@@ -54,9 +59,8 @@
 
 import com.google.android.collect.Lists;
 
-import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -71,30 +75,22 @@
  *  atest WmTests:DisplayAreaTest
  */
 @Presubmit
-public class DisplayAreaTest {
-    @Rule
-    public SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
-
-    private WindowManagerService mWms;
-
-    @Before
-    public void setup() {
-        mWms = mWmsRule.getWindowManagerService();
-    }
+@RunWith(WindowTestRunner.class)
+public class DisplayAreaTest extends WindowTestsBase {
 
     @Test
     public void testDisplayArea_positionChanged_throwsIfIncompatibleChild() {
-        DisplayArea<WindowContainer> parent = new DisplayArea<>(mWms, BELOW_TASKS, "Parent");
-        DisplayArea<WindowContainer> child = new DisplayArea<>(mWms, ANY, "Child");
+        DisplayArea<WindowContainer> parent = new DisplayArea<>(mWm, BELOW_TASKS, "Parent");
+        DisplayArea<WindowContainer> child = new DisplayArea<>(mWm, ANY, "Child");
 
         assertThrows(IllegalStateException.class, () -> parent.addChild(child, 0));
     }
 
     @Test
     public void testType_typeOf() {
-        assertEquals(ABOVE_TASKS, typeOf(new DisplayArea<>(mWms, ABOVE_TASKS, "test")));
-        assertEquals(ANY, typeOf(new DisplayArea<>(mWms, ANY, "test")));
-        assertEquals(BELOW_TASKS, typeOf(new DisplayArea<>(mWms, BELOW_TASKS, "test")));
+        assertEquals(ABOVE_TASKS, typeOf(new DisplayArea<>(mWm, ABOVE_TASKS, "test")));
+        assertEquals(ANY, typeOf(new DisplayArea<>(mWm, ANY, "test")));
+        assertEquals(BELOW_TASKS, typeOf(new DisplayArea<>(mWm, BELOW_TASKS, "test")));
 
         assertEquals(ABOVE_TASKS, typeOf(createWindowToken(TYPE_APPLICATION_OVERLAY)));
         assertEquals(ABOVE_TASKS, typeOf(createWindowToken(TYPE_PRESENTATION)));
@@ -134,10 +130,10 @@
 
     @Test
     public void testAsDisplayArea() {
-        final WindowContainer windowContainer = new WindowContainer(mWms);
-        final DisplayArea<WindowContainer> displayArea = new DisplayArea<>(mWms, ANY, "DA");
+        final WindowContainer windowContainer = new WindowContainer(mWm);
+        final DisplayArea<WindowContainer> displayArea = new DisplayArea<>(mWm, ANY, "DA");
         final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA", FEATURE_DEFAULT_TASK_CONTAINER);
+                mWm, "TDA", FEATURE_DEFAULT_TASK_CONTAINER);
 
         assertThat(windowContainer.asDisplayArea()).isNull();
         assertThat(displayArea.asDisplayArea()).isEqualTo(displayArea);
@@ -147,15 +143,15 @@
     @Test
     public void testForAllTaskDisplayAreas_onlyTraversesDisplayAreaOfTypeAny() {
         final RootDisplayArea root =
-                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWms);
+                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWm);
         final Function<TaskDisplayArea, Boolean> callback0 = tda -> false;
         final Consumer<TaskDisplayArea> callback1 = tda -> { };
         final BiFunction<TaskDisplayArea, Integer, Integer> callback2 = (tda, result) -> result;
         final Function<TaskDisplayArea, TaskDisplayArea> callback3 = tda -> null;
 
         // Don't traverse the child if the current DA has type BELOW_TASKS
-        final DisplayArea<WindowContainer> da1 = new DisplayArea<>(mWms, BELOW_TASKS, "DA1");
-        final DisplayArea<WindowContainer> da2 = new DisplayArea<>(mWms, BELOW_TASKS, "DA2");
+        final DisplayArea<WindowContainer> da1 = new DisplayArea<>(mWm, BELOW_TASKS, "DA1");
+        final DisplayArea<WindowContainer> da2 = new DisplayArea<>(mWm, BELOW_TASKS, "DA2");
         root.addChild(da1, POSITION_BOTTOM);
         da1.addChild(da2, POSITION_TOP);
         spyOn(da2);
@@ -168,8 +164,8 @@
         verifyZeroInteractions(da2);
 
         // Traverse the child if the current DA has type ANY
-        final DisplayArea<WindowContainer> da3 = new DisplayArea<>(mWms, ANY, "DA3");
-        final DisplayArea<WindowContainer> da4 = new DisplayArea<>(mWms, ANY, "DA4");
+        final DisplayArea<WindowContainer> da3 = new DisplayArea<>(mWm, ANY, "DA3");
+        final DisplayArea<WindowContainer> da4 = new DisplayArea<>(mWm, ANY, "DA4");
         root.addChild(da3, POSITION_TOP);
         da3.addChild(da4, POSITION_TOP);
         spyOn(da4);
@@ -187,8 +183,8 @@
                 callback3, true /* traverseTopToBottom */);
 
         // Don't traverse the child if the current DA has type ABOVE_TASKS
-        final DisplayArea<WindowContainer> da5 = new DisplayArea<>(mWms, ABOVE_TASKS, "DA5");
-        final DisplayArea<WindowContainer> da6 = new DisplayArea<>(mWms, ABOVE_TASKS, "DA6");
+        final DisplayArea<WindowContainer> da5 = new DisplayArea<>(mWm, ABOVE_TASKS, "DA5");
+        final DisplayArea<WindowContainer> da6 = new DisplayArea<>(mWm, ABOVE_TASKS, "DA6");
         root.addChild(da5, POSITION_TOP);
         da5.addChild(da6, POSITION_TOP);
         spyOn(da6);
@@ -204,17 +200,17 @@
     @Test
     public void testForAllTaskDisplayAreas_appliesOnTaskDisplayAreaInOrder() {
         final RootDisplayArea root =
-                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWms);
+                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWm);
         final DisplayArea<DisplayArea> da1 =
-                new DisplayArea<>(mWms, ANY, "DA1");
+                new DisplayArea<>(mWm, ANY, "DA1");
         final DisplayArea<DisplayArea> da2 =
-                new DisplayArea<>(mWms, ANY, "DA2");
+                new DisplayArea<>(mWm, ANY, "DA2");
         final TaskDisplayArea tda1 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
+                mWm, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
         final TaskDisplayArea tda2 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA2", FEATURE_VENDOR_FIRST);
+                mWm, "TDA2", FEATURE_VENDOR_FIRST);
         final TaskDisplayArea tda3 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA3", FEATURE_VENDOR_FIRST + 1);
+                mWm, "TDA3", FEATURE_VENDOR_FIRST + 1);
         root.addChild(da1, POSITION_TOP);
         root.addChild(da2, POSITION_TOP);
         da1.addChild(tda1, POSITION_TOP);
@@ -304,11 +300,11 @@
     @Test
     public void testForAllTaskDisplayAreas_returnsWhenCallbackReturnTrue() {
         final RootDisplayArea root =
-                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWms);
+                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWm);
         final TaskDisplayArea tda1 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
+                mWm, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
         final TaskDisplayArea tda2 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA2", FEATURE_VENDOR_FIRST);
+                mWm, "TDA2", FEATURE_VENDOR_FIRST);
         root.addChild(tda1, POSITION_TOP);
         root.addChild(tda2, POSITION_TOP);
 
@@ -332,11 +328,11 @@
     @Test
     public void testReduceOnAllTaskDisplayAreas_returnsTheAccumulativeResult() {
         final RootDisplayArea root =
-                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWms);
+                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWm);
         final TaskDisplayArea tda1 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
+                mWm, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
         final TaskDisplayArea tda2 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA2", FEATURE_VENDOR_FIRST);
+                mWm, "TDA2", FEATURE_VENDOR_FIRST);
         root.addChild(tda1, POSITION_TOP);
         root.addChild(tda2, POSITION_TOP);
 
@@ -358,11 +354,11 @@
     @Test
     public void testGetItemFromTaskDisplayAreas_returnsWhenCallbackReturnNotNull() {
         final RootDisplayArea root =
-                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWms);
+                new DisplayAreaPolicyBuilderTest.SurfacelessDisplayAreaRoot(mWm);
         final TaskDisplayArea tda1 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
+                mWm, "TDA1", FEATURE_DEFAULT_TASK_CONTAINER);
         final TaskDisplayArea tda2 = new TaskDisplayArea(null /* displayContent */,
-                mWms, "TDA2", FEATURE_VENDOR_FIRST);
+                mWm, "TDA2", FEATURE_VENDOR_FIRST);
         root.addChild(tda1, POSITION_TOP);
         root.addChild(tda2, POSITION_TOP);
 
@@ -394,9 +390,9 @@
                 parentBounds.right / 2, parentBounds.bottom);
         final Rect childBounds2 = new Rect(parentBounds.right / 2, parentBounds.top,
                 parentBounds.right, parentBounds.bottom);
-        TestDisplayArea parentDa = new TestDisplayArea(mWms, parentBounds);
-        TestDisplayArea childDa1 = new TestDisplayArea(mWms, childBounds1);
-        TestDisplayArea childDa2 = new TestDisplayArea(mWms, childBounds2);
+        TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds);
+        TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1);
+        TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2);
         parentDa.addChild(childDa1, 0);
         parentDa.addChild(childDa2, 1);
 
@@ -413,7 +409,7 @@
 
     @Test
     public void testGetOrientation() {
-        final DisplayArea.Tokens area = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "test");
+        final DisplayArea.Tokens area = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "test");
         final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY);
         spyOn(token);
         doReturn(mock(DisplayContent.class)).when(token).getDisplayContent();
@@ -440,7 +436,7 @@
 
     @Test
     public void testSetIgnoreOrientationRequest() {
-        final DisplayArea.Tokens area = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "test");
+        final DisplayArea.Tokens area = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "test");
         final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY);
         spyOn(token);
         doReturn(mock(DisplayContent.class)).when(token).getDisplayContent();
@@ -460,6 +456,28 @@
         assertEquals(ActivityInfo.SCREEN_ORIENTATION_UNSET, area.getOrientation());
     }
 
+    @Test
+    public void testSetIgnoreOrientationRequest_notCallSuperOnDescendantOrientationChanged() {
+        final TaskDisplayArea tda =
+                mDisplayContent.getDefaultTaskDisplayArea();
+        final Task stack =
+                new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build();
+        final ActivityRecord activity = stack.getTopNonFinishingActivity();
+
+        tda.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+
+        verify(tda).onDescendantOrientationChanged(any(), any());
+        verify(mDisplayContent, never()).onDescendantOrientationChanged(any(), any());
+
+        tda.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
+        activity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+
+        verify(tda, times(2)).onDescendantOrientationChanged(any(), any());
+        verify(mDisplayContent).onDescendantOrientationChanged(any(), any());
+    }
+
     private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
         private TestDisplayArea(WindowManagerService wms, Rect bounds) {
             super(wms, ANY, "half display area");
@@ -473,14 +491,14 @@
     }
 
     private WindowState createWindowState(WindowToken token) {
-        return new WindowState(mWms, mock(Session.class), new TestIWindow(), token,
+        return new WindowState(mWm, mock(Session.class), new TestIWindow(), token,
                 null /* parentWindow */, 0 /* appOp */, new WindowManager.LayoutParams(),
                 View.VISIBLE, 0 /* ownerId */, 0 /* showUserId */,
                 false /* ownerCanAddInternalSystemWindow */);
     }
 
     private WindowToken createWindowToken(int type) {
-        return new WindowToken(mWmsRule.getWindowManagerService(), new Binder(),
+        return new WindowToken(mWm, new Binder(),
                 type, false /* persist */, null /* displayContent */,
                 false /* canManageTokens */);
     }