/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;

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.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE;
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.WindowContainer.POSITION_TOP;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doCallRealMethod;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.WindowConfiguration;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.view.InsetsVisibilities;
import android.view.WindowManager;

import androidx.test.filters.MediumTest;

import com.android.internal.policy.SystemBarUtils;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.statusbar.StatusBarManagerInternal;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;

/**
 * Tests for Size Compatibility mode.
 *
 * Build/Install/Run:
 *  atest WmTests:SizeCompatTests
 */
@MediumTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class SizeCompatTests extends WindowTestsBase {
    private static final String CONFIG_NEVER_CONSTRAIN_DISPLAY_APIS =
            "never_constrain_display_apis";
    private static final String CONFIG_ALWAYS_CONSTRAIN_DISPLAY_APIS =
            "always_constrain_display_apis";
    private static final String CONFIG_NEVER_CONSTRAIN_DISPLAY_APIS_ALL_PACKAGES =
            "never_constrain_display_apis_all_packages";

    @Rule
    public TestRule compatChangeRule = new PlatformCompatChangeRule();

    private Task mTask;
    private ActivityRecord mActivity;
    private ActivityMetricsLogger mActivityMetricsLogger;
    private Properties mInitialConstrainDisplayApisFlags;

    @Before
    public void setUp() throws Exception {
        mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
        clearInvocations(mActivityMetricsLogger);
        doReturn(mActivityMetricsLogger).when(mAtm.mTaskSupervisor).getActivityMetricsLogger();
        mInitialConstrainDisplayApisFlags = DeviceConfig.getProperties(
                NAMESPACE_CONSTRAIN_DISPLAY_APIS);
        // Provide empty default values for the configs.
        setNeverConstrainDisplayApisFlag("", true);
        setNeverConstrainDisplayApisAllPackagesFlag(false, true);
        setAlwaysConstrainDisplayApisFlag("", true);
    }

    @After
    public void tearDown() throws Exception {
        DeviceConfig.setProperties(mInitialConstrainDisplayApisFlags);
    }

    private void setUpApp(DisplayContent display) {
        mTask = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true).build();
        mActivity = mTask.getTopNonFinishingActivity();
    }

    private void setUpDisplaySizeWithApp(int dw, int dh) {
        final TestDisplayContent.Builder builder = new TestDisplayContent.Builder(mAtm, dw, dh);
        setUpApp(builder.build());
    }

    @Test
    public void testRestartProcessIfVisible() {
        setUpDisplaySizeWithApp(1000, 2500);
        doNothing().when(mSupervisor).scheduleRestartTimeout(mActivity);
        mActivity.mVisibleRequested = true;
        mActivity.setSavedState(null /* savedState */);
        mActivity.setState(RESUMED, "testRestart");
        prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);

        final Rect originalOverrideBounds = new Rect(mActivity.getBounds());
        resizeDisplay(mTask.mDisplayContent, 600, 1200);
        // The visible activity should recompute configuration according to the last parent bounds.
        mAtm.mActivityClientController.restartActivityProcessIfVisible(mActivity.token);

        assertEquals(RESTARTING_PROCESS, mActivity.getState());
        assertNotEquals(originalOverrideBounds, mActivity.getBounds());
    }

    @Test
    public void testFixedAspectRatioBoundsWithDecorInSquareDisplay() {
        final int notchHeight = 100;
        setUpApp(new TestDisplayContent.Builder(mAtm, 600, 800).setNotch(notchHeight).build());

        final Rect displayBounds = mActivity.mDisplayContent.getWindowConfiguration().getBounds();
        final float aspectRatio = 1.2f;
        mActivity.info.setMaxAspectRatio(aspectRatio);
        mActivity.info.setMinAspectRatio(aspectRatio);
        prepareUnresizable(mActivity, -1f, SCREEN_ORIENTATION_UNSPECIFIED);
        final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();

        // The parent configuration doesn't change since the first resolved configuration, so the
        // activity should fit in the parent naturally (size=583x700, appBounds=[9, 100 - 592, 800],
        // horizontal offset = round((600 - 583) / 2) = 9)).
        assertFitted();
        final int offsetX = (int) ((1f + displayBounds.width() - appBounds.width()) / 2);
        // The bounds must be horizontal centered.
        assertEquals(offsetX, appBounds.left);
        assertEquals(appBounds.height(), displayBounds.height() - notchHeight);
        // Ensure the app bounds keep the declared aspect ratio.
        assertEquals(appBounds.height(), appBounds.width() * aspectRatio, 0.5f /* delta */);
        // The decor height should be a part of the effective bounds.
        assertEquals(mActivity.getBounds().height(), appBounds.height() + notchHeight);
        // Activity max bounds should be sandboxed; activity is letterboxed due to aspect ratio.
        assertActivityMaxBoundsSandboxed();
        // Activity max bounds ignore notch, since an app can be shown past the notch (although app
        // is currently limited by the notch).
        assertThat(mActivity.getWindowConfiguration().getMaxBounds().height())
                .isEqualTo(displayBounds.height());

        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
        assertFitted();

        // After the orientation of activity is changed, the display is rotated, the aspect
        // ratio should be the same (bounds=[0, 0 - 800, 583], appBounds=[100, 0 - 800, 583]).
        assertEquals(appBounds.width(), appBounds.height() * aspectRatio, 0.5f /* delta */);
        // Activity max bounds are sandboxed.
        assertActivityMaxBoundsSandboxed();

        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
        assertFitted();
        // Activity max bounds should be sandboxed; activity is letterboxed due to aspect ratio.
        assertActivityMaxBoundsSandboxed();
        // Activity max bounds ignore notch, since an app can be shown past the notch (although app
        // is currently limited by the notch).
        assertThat(mActivity.getWindowConfiguration().getMaxBounds().height())
                .isEqualTo(displayBounds.height());
    }

    @Test
    public void testFixedScreenConfigurationWhenMovingToDisplay() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make a new less-tall display with lower density
        final DisplayContent newDisplay =
                new TestDisplayContent.Builder(mAtm, 1000, 2000)
                        .setDensityDpi(200).build();

        prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);

        final Rect originalBounds = new Rect(mActivity.getBounds());
        final int originalDpi = mActivity.getConfiguration().densityDpi;

        // Move the non-resizable activity to the new display.
        mTask.reparent(newDisplay.getDefaultTaskDisplayArea(), true /* onTop */);

        assertEquals(originalBounds.width(), mActivity.getBounds().width());
        assertEquals(originalBounds.height(), mActivity.getBounds().height());
        assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
        // Activity is sandboxed; it is in size compat mode since it is not resizable and has a
        // max aspect ratio.
        assertActivityMaxBoundsSandboxed();
        assertScaled();
    }

    @Test
    public void testFixedScreenBoundsWhenDisplaySizeChanged() {
        setUpDisplaySizeWithApp(1000, 2500);
        prepareUnresizable(mActivity, -1f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        final DisplayContent display = mActivity.mDisplayContent;
        assertFitted();
        // Activity inherits bounds from TaskDisplayArea, since not sandboxed.
        assertMaxBoundsInheritDisplayAreaBounds();

        final Rect origBounds = new Rect(mActivity.getBounds());
        final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();

        // Change the size of current display.
        resizeDisplay(display, 1000, 2000);
        // The bounds should be [100, 0 - 1100, 2500].
        assertEquals(origBounds.width(), currentBounds.width());
        assertEquals(origBounds.height(), currentBounds.height());
        assertScaled();

        // The scale is 2000/2500=0.8. The horizontal centered offset is (1000-(1000*0.8))/2=100.
        final float scale = (float) display.mBaseDisplayHeight / currentBounds.height();
        final int offsetX = (int) (display.mBaseDisplayWidth - (origBounds.width() * scale)) / 2;
        assertEquals(offsetX, currentBounds.left);

        // The position of configuration bounds should be the same as compat bounds.
        assertEquals(mActivity.getBounds().left, currentBounds.left);
        assertEquals(mActivity.getBounds().top, currentBounds.top);
        // Activity is sandboxed to the offset size compat bounds.
        assertActivityMaxBoundsSandboxed();

        // Change display size to a different orientation
        resizeDisplay(display, 2000, 1000);
        // The bounds should be [800, 0 - 1800, 2500].
        assertEquals(origBounds.width(), currentBounds.width());
        assertEquals(origBounds.height(), currentBounds.height());
        assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
        assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
        // Activity is sandboxed to the offset size compat bounds.
        assertActivityMaxBoundsSandboxed();

        // The previous resize operation doesn't consider the rotation change after size changed.
        // These setups apply the requested orientation to rotation as real case that the top fixed
        // portrait activity will determine the display rotation.
        final DisplayRotation displayRotation = display.getDisplayRotation();
        doCallRealMethod().when(displayRotation).updateRotationUnchecked(anyBoolean());
        // Skip unrelated layout procedures.
        mAtm.deferWindowLayout();
        display.reconfigureDisplayLocked();
        displayRotation.updateOrientation(display.getOrientation(), true /* forceUpdate */);
        display.sendNewConfiguration();

        assertEquals(Configuration.ORIENTATION_PORTRAIT, display.getConfiguration().orientation);
        assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
        // The size should still be in portrait [100, 0 - 1100, 2500] = 1000x2500.
        assertEquals(origBounds.width(), currentBounds.width());
        assertEquals(origBounds.height(), currentBounds.height());
        assertEquals(offsetX, currentBounds.left);
        assertScaled();
        // Activity is sandboxed due to size compat mode.
        assertActivityMaxBoundsSandboxed();

        final WindowState appWindow = addWindowToActivity(mActivity);
        assertTrue(mActivity.hasSizeCompatBounds());
        assertEquals("App window must use size compat bounds for layout in screen space",
                mActivity.getBounds(), appWindow.getBounds());
    }

    @Test
    public void testLetterboxFullscreenBoundsAndNotImeAttachable() {
        final int displayWidth = 2500;
        setUpDisplaySizeWithApp(displayWidth, 1000);

        final float maxAspect = 1.5f;
        prepareUnresizable(mActivity, maxAspect, SCREEN_ORIENTATION_LANDSCAPE);
        assertFitted();

        final Rect bounds = mActivity.getBounds();
        assertEquals(bounds.width(), bounds.height() * maxAspect, 0.0001f /* delta */);
        // The position should be horizontal centered.
        assertEquals((displayWidth - bounds.width()) / 2, bounds.left);
        // Activity max bounds should be sandboxed since it is letterboxed.
        assertActivityMaxBoundsSandboxed();

        mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
        // Make sure IME cannot attach to the app, otherwise IME window will also be shifted.
        assertFalse(mActivity.mDisplayContent.shouldImeAttachedToApp());

        // Recompute the natural configuration without resolving size compat configuration.
        mActivity.clearSizeCompatMode();
        mActivity.onConfigurationChanged(mTask.getConfiguration());
        // It should keep non-attachable because the resolved bounds will be computed according to
        // the aspect ratio that won't match its parent bounds.
        assertFalse(mActivity.mDisplayContent.shouldImeAttachedToApp());
        // Activity max bounds should be sandboxed since it is letterboxed.
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testIsLetterboxed_activityShowsWallpaper_returnsFalse() {
        setUpDisplaySizeWithApp(1000, 2500);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
        final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, mActivity, "window");

        assertEquals(window, mActivity.findMainWindow());

        spyOn(mActivity.mLetterboxUiController);
        doReturn(true).when(mActivity.mLetterboxUiController)
                .isSurfaceReadyAndVisible(any());

        assertTrue(mActivity.mLetterboxUiController.shouldShowLetterboxUi(
                mActivity.findMainWindow()));

        window.mAttrs.flags |= FLAG_SHOW_WALLPAPER;

        assertFalse(mActivity.mLetterboxUiController.shouldShowLetterboxUi(
                mActivity.findMainWindow()));
    }

    @Test
    public void testAspectRatioMatchParentBoundsAndImeAttachable() {
        setUpApp(new TestDisplayContent.Builder(mAtm, 1000, 2000).build());
        prepareUnresizable(mActivity, 2f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
        assertFitted();

        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
        mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
        mActivity.mDisplayContent.setImeInputTarget(
                mActivity.mDisplayContent.getImeTarget(IME_TARGET_LAYERING).getWindow());
        // Because the aspect ratio of display doesn't exceed the max aspect ratio of activity.
        // The activity should still fill its parent container and IME can attach to the activity.
        assertTrue(mActivity.matchParentBounds());
        assertTrue(mActivity.mDisplayContent.shouldImeAttachedToApp());

        final Rect letterboxInnerBounds = new Rect();
        mActivity.getLetterboxInnerBounds(letterboxInnerBounds);
        // The activity should not have letterbox.
        assertTrue(letterboxInnerBounds.isEmpty());
    }

    @Test
    public void testMoveToDifferentOrientationDisplay() {
        setUpDisplaySizeWithApp(1000, 2500);
        prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        assertFitted();

        final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
        final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds();
        final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds());

        final int notchHeight = 100;
        final DisplayContent newDisplay = new TestDisplayContent.Builder(mAtm, 2000, 1000)
                .setCanRotate(false).setNotch(notchHeight).build();

        // Move the non-resizable activity to the new display.
        mTask.reparent(newDisplay.getDefaultTaskDisplayArea(), true /* onTop */);
        // The configuration bounds [820, 0 - 1820, 2500] should keep the same.
        assertEquals(originalBounds.width(), currentBounds.width());
        assertEquals(originalBounds.height(), currentBounds.height());
        assertScaled();
        // Activity max bounds are sandboxed due to size compat mode on the new display.
        assertActivityMaxBoundsSandboxed();

        final Rect newDisplayBounds = newDisplay.getWindowConfiguration().getBounds();
        // The scaled bounds should exclude notch area (1000 - 100 == 360 * 2500 / 1000 = 900).
        assertEquals(newDisplayBounds.height() - notchHeight,
                (int) ((float) mActivity.getBounds().width() * originalBounds.height()
                        / originalBounds.width()));

        // Recompute the natural configuration in the new display.
        mActivity.clearSizeCompatMode();
        mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
        // Because the display cannot rotate, the portrait activity will fit the short side of
        // display with keeping portrait bounds [200, 0 - 700, 1000] in center.
        assertEquals(newDisplayBounds.height(), currentBounds.height());
        assertEquals(currentAppBounds.height() * newDisplayBounds.height()
                / newDisplayBounds.width(), currentAppBounds.width());
        assertFitted();
        // The appBounds should be [200, 100 - 700, 1000].
        final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
        assertEquals(currentBounds.width(), appBounds.width());
        assertEquals(currentBounds.height() - notchHeight, appBounds.height());
        // Activity max bounds are sandboxed due to letterboxing from orientation mismatch with
        // display.
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testFixedOrientationRotateCutoutDisplay() {
        // Create a display with a notch/cutout
        final int notchHeight = 60;
        final int width = 1000;
        setUpApp(new TestDisplayContent.Builder(mAtm, width, 2500)
                .setNotch(notchHeight).build());
        // Bounds=[0, 0 - 1000, 1400], AppBounds=[0, 60 - 1000, 1460].
        final float maxAspect = 1.4f;
        prepareUnresizable(mActivity, 1.4f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);

        final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
        final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
        final Rect origBounds = new Rect(currentBounds);
        final Rect origAppBounds = new Rect(appBounds);

        // Activity is sandboxed, and bounds include the area consumed by the notch.
        assertActivityMaxBoundsSandboxed();
        assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds().height())
                .isEqualTo(Math.round(width * maxAspect) + notchHeight);

        // Although the activity is fixed orientation, force rotate the display.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_270);
        assertEquals(ROTATION_270, mTask.getWindowConfiguration().getRotation());

        assertEquals(origBounds.width(), currentBounds.width());
        // Make sure the app size is the same
        assertEquals(origAppBounds.width(), appBounds.width());
        assertEquals(origAppBounds.height(), appBounds.height());
        // The activity is 1000x1400 and the display is 2500x1000.
        assertScaled();
        // The position in configuration should be global coordinates.
        assertEquals(mActivity.getBounds().left, currentBounds.left);
        assertEquals(mActivity.getBounds().top, currentBounds.top);

        // Activity max bounds are sandboxed due to size compat mode.
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testFixedAspectRatioOrientationChangeOrientation() {
        setUpDisplaySizeWithApp(1000, 2500);

        final float maxAspect = 1.4f;
        prepareUnresizable(mActivity, maxAspect, SCREEN_ORIENTATION_PORTRAIT);
        // The display aspect ratio 2.5 > 1.4 (max of activity), so the size is fitted.
        assertFitted();

        final Rect originalBounds = new Rect(mActivity.getBounds());
        final Rect originalAppBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds());

        assertEquals((int) (originalBounds.width() * maxAspect), originalBounds.height());
        // Activity is sandboxed due to fixed aspect ratio.
        assertActivityMaxBoundsSandboxed();

        // Change the fixed orientation.
        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);

        assertFitted();
        assertEquals(originalBounds.width(), mActivity.getBounds().height());
        assertEquals(originalBounds.height(), mActivity.getBounds().width());
        assertEquals(originalAppBounds.width(),
                mActivity.getWindowConfiguration().getAppBounds().height());
        assertEquals(originalAppBounds.height(),
                mActivity.getWindowConfiguration().getAppBounds().width());
        // Activity is sandboxed due to fixed aspect ratio.
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testFixedScreenLayoutSizeBits() {
        setUpDisplaySizeWithApp(1000, 2500);
        final int fixedScreenLayout = Configuration.SCREENLAYOUT_LONG_NO
                | Configuration.SCREENLAYOUT_SIZE_NORMAL
                | Configuration.SCREENLAYOUT_COMPAT_NEEDED;
        final int layoutMask = Configuration.SCREENLAYOUT_LONG_MASK
                | Configuration.SCREENLAYOUT_SIZE_MASK
                | Configuration.SCREENLAYOUT_LAYOUTDIR_MASK
                | Configuration.SCREENLAYOUT_COMPAT_NEEDED;
        Configuration c = new Configuration(mTask.getRequestedOverrideConfiguration());
        c.screenLayout = fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_LTR;
        mTask.onRequestedOverrideConfigurationChanged(c);
        prepareUnresizable(mActivity, 1.5f, SCREEN_ORIENTATION_UNSPECIFIED);

        // The initial configuration should inherit from parent.
        assertEquals(fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_LTR,
                mActivity.getConfiguration().screenLayout & layoutMask);

        mTask.getConfiguration().screenLayout = Configuration.SCREENLAYOUT_LAYOUTDIR_RTL
                | Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_LARGE;
        mActivity.onConfigurationChanged(mTask.getConfiguration());

        // The size and aspect ratio bits don't change, but the layout direction should be updated.
        assertEquals(fixedScreenLayout | Configuration.SCREENLAYOUT_LAYOUTDIR_RTL,
                mActivity.getConfiguration().screenLayout & layoutMask);
    }

    @Test
    public void testResetNonVisibleActivity() {
        setUpDisplaySizeWithApp(1000, 2500);
        prepareUnresizable(mActivity, 1.5f, SCREEN_ORIENTATION_UNSPECIFIED);
        final DisplayContent display = mTask.mDisplayContent;
        // Resize the display so the activity is in size compatibility mode.
        resizeDisplay(display, 900, 1800);

        mActivity.setState(STOPPED, "testSizeCompatMode");
        mActivity.mVisibleRequested = false;
        mActivity.visibleIgnoringKeyguard = false;
        mActivity.app.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
        mActivity.app.computeProcessActivityState();

        // Simulate the display changes orientation.
        final Configuration rotatedConfig = rotateDisplay(display, ROTATION_90);
        // Size compatibility mode is able to handle orientation change so the process shouldn't be
        // restarted and the override configuration won't be cleared.
        verify(mActivity, never()).restartProcessIfVisible();
        assertScaled();
        // Activity max bounds are sandboxed due to size compat mode, even if is not visible.
        assertActivityMaxBoundsSandboxed();

        // Change display density
        display.mBaseDisplayDensity = (int) (0.7f * display.mBaseDisplayDensity);
        display.computeScreenConfiguration(rotatedConfig);
        mAtm.mAmInternal = mock(ActivityManagerInternal.class);
        display.onRequestedOverrideConfigurationChanged(rotatedConfig);

        // The override configuration should be reset and the activity's process will be killed.
        assertFitted();
        verify(mActivity).restartProcessIfVisible();
        waitHandlerIdle(mAtm.mH);
        verify(mAtm.mAmInternal).killProcess(
                eq(mActivity.app.mName), eq(mActivity.app.mUid), anyString());
    }

    /**
     * Ensures that {@link TaskOrganizerController} can receive callback about the activity in size
     * compatibility mode.
     */
    @Test
    public void testHandleActivitySizeCompatModeChanged() {
        setUpDisplaySizeWithApp(1000, 2000);
        doReturn(true).when(mTask).isOrganized();
        mActivity.setState(RESUMED, "testHandleActivitySizeCompatModeChanged");
        prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        assertFitted();

        // Resize the display so that the activity exercises size-compat mode.
        resizeDisplay(mTask.mDisplayContent, 1000, 2500);

        // Expect the exact token when the activity is in size compatibility mode.
        verify(mTask).onSizeCompatActivityChanged();
        ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();

        assertTrue(taskInfo.topActivityInSizeCompat);

        // Make the activity resizable again by restarting it
        clearInvocations(mTask);
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
        mActivity.mVisibleRequested = true;
        mActivity.restartProcessIfVisible();
        // The full lifecycle isn't hooked up so manually set state to resumed
        mActivity.setState(RESUMED, "testHandleActivitySizeCompatModeChanged");
        mTask.mDisplayContent.handleActivitySizeCompatModeIfNeeded(mActivity);

        // Expect null token when switching to non-size-compat mode activity.
        verify(mTask).onSizeCompatActivityChanged();
        taskInfo = mTask.getTaskInfo();

        assertFalse(taskInfo.topActivityInSizeCompat);
    }

    @Test
    public void testHandleActivitySizeCompatModeChangedOnDifferentTask() {
        setUpDisplaySizeWithApp(1000, 2000);
        doReturn(true).when(mTask).isOrganized();
        mActivity.setState(RESUMED, "testHandleActivitySizeCompatModeChanged");
        prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
        assertFitted();

        // Resize the display so that the activity exercises size-compat mode.
        resizeDisplay(mTask.mDisplayContent, 1000, 2500);

        // Expect the exact token when the activity is in size compatibility mode.
        verify(mTask).onSizeCompatActivityChanged();
        ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo();

        assertTrue(taskInfo.topActivityInSizeCompat);

        // Create another Task to hold another size compat activity.
        clearInvocations(mTask);
        final Task secondTask = new TaskBuilder(mSupervisor).setDisplay(mTask.getDisplayContent())
                .setCreateActivity(true).build();
        final ActivityRecord secondActivity = secondTask.getTopNonFinishingActivity();
        doReturn(true).when(secondTask).isOrganized();
        secondActivity.setState(RESUMED,
                "testHandleActivitySizeCompatModeChanged");
        prepareUnresizable(secondActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);

        // Resize the display so that the activity exercises size-compat mode.
        resizeDisplay(mTask.mDisplayContent, 1000, 3000);

        // Expect the exact token when the activity is in size compatibility mode.
        verify(secondTask).onSizeCompatActivityChanged();
        verify(mTask, never()).onSizeCompatActivityChanged();
        taskInfo = secondTask.getTaskInfo();

        assertTrue(taskInfo.topActivityInSizeCompat);
    }

    @Test
    public void testShouldCreateCompatDisplayInsetsOnResizeableTask() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
                .build();
        assertFalse(activity.shouldCreateCompatDisplayInsets());

        // The non-resizable activity should not be size compat because it is on a resizable task
        // in multi-window mode.
        mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
        // Activity should not be sandboxed.
        assertMaxBoundsInheritDisplayAreaBounds();

        // The non-resizable activity should not be size compat because the display support
        // changing windowing mode from fullscreen to freeform.
        mTask.mDisplayContent.getDefaultTaskDisplayArea()
                .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
        mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
        // Activity should not be sandboxed.
        assertMaxBoundsInheritDisplayAreaBounds();
    }

    @Test
    public void testShouldCreateCompatDisplayInsetsWhenUnresizeableAndSupportsSizeChangesTrue() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */true,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    public void testShouldNotCreateCompatDisplayInsetsWhenRootActivityIsResizeable() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    public void testShouldCreateCompatDisplayInsetsWhenResizeableAndSupportsSizeChangesFalse() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    public void
            testShouldCreateCompatDisplayInsetsWhenUnfixedOrientationSupportsSizeChangesFalse() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.FORCE_RESIZE_APP})
    public void testShouldCreateCompatDisplayInsetsWhenForceResizeAppOverrideSet() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP})
    public void testShouldCreateCompatDisplayInsetsWhenForceNonResizeOverrideSet() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */true,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        assertTrue(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP})
    public void testShouldCreateCompatDisplayInsetsWhenForceNonResizeSetAndUnfixedOrientation() {
        setUpDisplaySizeWithApp(1000, 2500);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */true,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        assertTrue(activity.shouldCreateCompatDisplayInsets());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
    public void testNeverSandboxDisplayApis_configEnabled_sandboxingNotApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should not be sandboxed, even though it is letterboxed.
        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(activity.getDisplayArea().getBounds());
    }

    @Test
    @DisableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS})
    public void testNeverSandboxDisplayApis_configDisabled_sandboxingApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterboxed and the config being disabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    public void testNeverConstrainDisplayApisDeviceConfig_allPackagesFlagTrue_sandboxNotApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        setNeverConstrainDisplayApisAllPackagesFlag(true, false);
        // Setting 'never_constrain_display_apis' as well to make sure it is ignored.
        setNeverConstrainDisplayApisFlag("com.android.other::,com.android.other2::", false);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should not be sandboxed, even though it is letterboxed.
        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(activity.getDisplayArea().getBounds());
    }

    @Test
    public void testNeverConstrainDisplayApisDeviceConfig_packageInRange_sandboxingNotApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        setNeverConstrainDisplayApisFlag(
                "com.android.frameworks.wmtests:20:,com.android.other::,"
                        + "com.android.frameworks.wmtests:0:10", false);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should not be sandboxed, even though it is letterboxed.
        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(activity.getDisplayArea().getBounds());
    }

    @Test
    public void testNeverConstrainDisplayApisDeviceConfig_packageOutsideRange_sandboxingApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        setNeverConstrainDisplayApisFlag("com.android.other::,com.android.frameworks.wmtests:1:5",
                false);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterboxed and the mismatch with flag.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    public void testNeverConstrainDisplayApisDeviceConfig_packageNotInFlag_sandboxingApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        setNeverConstrainDisplayApisFlag("com.android.other::,com.android.other2::", false);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterboxed and the mismatch with flag.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
    public void testAlwaysSandboxDisplayApis_configEnabled_sandboxingApplied_unresizable() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterboxed and the config being enabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @DisableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
    public void testAlwaysSandboxDisplayApis_configDisabled_sandboxingApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Activity max bounds should be sandboxed due to letterbox and the config being disabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS})
    public void testAlwaysSandboxDisplayApis_configEnabled_sandboxingApplied_resizableSplit() {
        setUpDisplaySizeWithApp(1000, 2800);
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_RESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, activity.getDisplayContent());

        // Activity max bounds should be sandboxed due the config being enabled.
        assertFalse(activity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed(activity);

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP,
                false /*moveParents*/, "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 1400);
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());

        // Resizable activity is sandboxed due to config being enabled.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    public void testAlwaysConstrainDisplayApisDeviceConfig_packageInRange_sandboxingApplied() {
        setUpDisplaySizeWithApp(1000, 1200);

        setAlwaysConstrainDisplayApisFlag(
                "com.android.frameworks.wmtests:20:,com.android.other::,"
                        + "com.android.frameworks.wmtests:0:10", false);

        // Make the task root resizable.
        mActivity.info.resizeMode = RESIZE_MODE_RESIZEABLE;

        // Create an activity with a max aspect ratio on the same task.
        final ActivityRecord activity = buildActivityRecord(/* supportsSizeChanges= */false,
                RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);

        // Resizable activity is sandboxed due to match with flag.
        assertActivityMaxBoundsSandboxed(activity);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    public void testOverrideMinAspectRatioMedium() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override forces the activity into a 3:2 aspect ratio
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    public void testOverrideMinAspectRatioLowerThanManifest() {
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1400, 1800)
                .setNotch(200).setSystemDecorations(true).build();
        mTask = new TaskBuilder(mSupervisor).setDisplay(display).build();

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setMinAspectRatio(2f)
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override should have no effect, because the manifest aspect ratio is
        // larger (2:1)
        final Rect appBounds = activity.getWindowConfiguration().getAppBounds();
        assertEquals("App bounds must have min aspect ratio", 2f,
                (float) appBounds.height() / appBounds.width(), 0.0001f /* delta */);
        assertEquals("Long side must fit task",
                mTask.getWindowConfiguration().getAppBounds().height(), appBounds.height());
        assertEquals("Bounds can include insets", mTask.getBounds().height(),
                activity.getBounds().height());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
    public void testOverrideMinAspectRatioLargerThanManifest() {
        setUpDisplaySizeWithApp(1400, 1600);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setMinAspectRatio(1.1f)
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override should have no effect, because the manifest aspect ratio is
        // larger (2:1)
        assertEquals(1600, activity.getBounds().height());
        assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
    public void testOverrideMinAspectRatioLarge() {
        setUpDisplaySizeWithApp(1500, 1600);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override forces the activity into a 16:9 aspect ratio
        assertEquals(1600, activity.getBounds().height());
        assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
    public void testOverrideMinAspectRatio_Both() {
        // If multiple override aspect ratios are set, we should use the largest one

        setUpDisplaySizeWithApp(1400, 1600);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override forces the activity into a 16:9 aspect ratio
        assertEquals(1600, activity.getBounds().height());
        assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    public void testOverrideMinAspectRatioScreenOrientationNotSetThenChangedToPortrait() {
        // In this test, the activity's orientation isn't fixed to portrait, therefore the override
        // isn't applied.

        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override should have no effect
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1000, activity.getBounds().width());

        // After changing the orientation to portrait the override should be applied.
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        activity.clearSizeCompatMode();

        // The per-package override forces the activity into a 3:2 aspect ratio
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    public void testOverrideMinAspectRatioScreenOrientationLandscapeThenChangedToPortrait() {
        // In this test, the activity's orientation isn't fixed to portrait, therefore the override
        // isn't applied.

        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override should have no effect
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1000, activity.getBounds().width());

        // After changing the orientation to portrait the override should be applied.
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        activity.clearSizeCompatMode();

        // The per-package override forces the activity into a 3:2 aspect ratio
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    public void testOverrideMinAspectRatioScreenOrientationPortraitThenChangedToUnspecified() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override forces the activity into a 3:2 aspect ratio
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
                activity.getBounds().width(), 0.5);

        // After changing the orientation to landscape the override shouldn't be applied.
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        activity.clearSizeCompatMode();

        // The per-package override should have no effect
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1000, activity.getBounds().width());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY})
    public void testOverrideMinAspectRatioPortraitOnlyDisabledScreenOrientationNotSet() {
        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override forces the activity into a 3:2 aspect ratio
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY})
    public void testOverrideMinAspectRatioPortraitOnlyDisabledScreenOrientationLandscape() {
        // In this test, the activity's orientation isn't fixed to portrait, therefore the override
        // isn't applied.

        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override forces the activity into a 3:2 aspect ratio
        assertEquals(1000 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
                activity.getBounds().height(), 0.5);
        assertEquals(1000, activity.getBounds().width());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
    public void testOverrideMinAspectRatioWithoutGlobalOverride() {
        // In this test, only OVERRIDE_MIN_ASPECT_RATIO_1_5 is set, which has no effect without
        // OVERRIDE_MIN_ASPECT_RATIO being also set.

        setUpDisplaySizeWithApp(1000, 1200);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // The per-package override should have no effect
        assertEquals(1200, activity.getBounds().height());
        assertEquals(1000, activity.getBounds().width());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE})
    public void testOverrideMinAspectRatioLargeForResizableAppInSplitScreen() {
        setUpDisplaySizeWithApp(/* dw= */ 1000, /* dh= */ 2800);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, activity.getDisplayContent());

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 1400);
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());

        // The per-package override forces the activity into a 16:9 aspect ratio
        assertEquals(1400, activity.getBounds().height());
        assertEquals(1400 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    public void testLaunchWithFixedRotationTransform() {
        final int dw = 1000;
        final int dh = 2500;
        final int notchHeight = 200;
        setUpApp(new TestDisplayContent.Builder(mAtm, dw, dh).setNotch(notchHeight).build());
        addStatusBar(mActivity.mDisplayContent);

        mActivity.setVisible(false);
        mActivity.mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_OPEN);
        mActivity.mDisplayContent.mOpeningApps.add(mActivity);
        final float maxAspect = 1.8f;
        prepareUnresizable(mActivity, maxAspect, SCREEN_ORIENTATION_LANDSCAPE);

        assertFitted();
        assertTrue(mActivity.isFixedRotationTransforming());
        // Display keeps in original orientation.
        assertEquals(Configuration.ORIENTATION_PORTRAIT,
                mActivity.mDisplayContent.getConfiguration().orientation);
        // The width should be restricted by the max aspect ratio = 1000 * 1.8 = 1800.
        assertEquals((int) (dw * maxAspect), mActivity.getBounds().width());
        // The notch is at the left side of the landscape activity. The bounds should be horizontal
        // centered in the remaining area [200, 0 - 2500, 1000], so its left should be
        // 200 + (2300 - 1800) / 2 = 450. The bounds should be [450, 0 - 2250, 1000].
        assertEquals(notchHeight + (dh - notchHeight - mActivity.getBounds().width()) / 2,
                mActivity.getBounds().left);

        // The letterbox needs a main window to layout.
        final WindowState w = addWindowToActivity(mActivity);
        // Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}.
        mActivity.mRootWindowContainer.performSurfacePlacement();
        // The letterbox insets should be [450, 0 - 250, 0].
        assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0),
                mActivity.getLetterboxInsets());

        final DisplayPolicy displayPolicy = mActivity.mDisplayContent.getDisplayPolicy();
        // The activity doesn't fill the display, so the letterbox of the rotated activity is
        // overlapped with the rotated content frame of status bar. Hence the status bar shouldn't
        // be transparent.
        assertFalse(displayPolicy.isFullyTransparentAllowed(w, ITYPE_STATUS_BAR));

        // Activity is sandboxed.
        assertActivityMaxBoundsSandboxed();

        // Make the activity fill the display.
        prepareUnresizable(mActivity, 10 /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE);
        w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
        // Refresh the letterbox.
        mActivity.mRootWindowContainer.performSurfacePlacement();

        // The letterbox should only cover the notch area, so status bar can be transparent.
        assertEquals(new Rect(notchHeight, 0, 0, 0), mActivity.getLetterboxInsets());
        assertTrue(displayPolicy.isFullyTransparentAllowed(w, ITYPE_STATUS_BAR));
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppLaunchedLetterbox() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app without max aspect.
        prepareUnresizable(mActivity, /* maxAspect= */ 0, SCREEN_ORIENTATION_PORTRAIT);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // Display shouldn't be rotated.
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED,
                mActivity.mDisplayContent.getLastOrientation());
        assertTrue(displayBounds.width() > displayBounds.height());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed();

        // Activity bounds should be 700x1400 with the ratio as the display.
        assertEquals(displayBounds.height(), activityBounds.height());
        assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
                activityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppRespectMinAspectRatio() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app with min aspect ratio higher that aspect ratio override for fixed
        // orientation letterbox.
        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);
        mActivity.info.setMinAspectRatio(3);
        prepareUnresizable(mActivity, /* maxAspect= */ 0, SCREEN_ORIENTATION_PORTRAIT);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // Display shouldn't be rotated.
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED,
                mActivity.mDisplayContent.getLastOrientation());
        assertTrue(displayBounds.width() > displayBounds.height());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Activity bounds should respect minimum aspect ratio for activity.
        assertEquals(displayBounds.height(), activityBounds.height());
        assertEquals((int) Math.rint(displayBounds.height()
                        / mActivity.info.getManifestMinAspectRatio()),
                activityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppRespectMaxAspectRatio() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app with max aspect ratio lower that aspect ratio override for fixed
        // orientation letterbox.
        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(3);
        prepareUnresizable(mActivity, /* maxAspect= */ 2, SCREEN_ORIENTATION_PORTRAIT);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // Display shouldn't be rotated.
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED,
                mActivity.mDisplayContent.getLastOrientation());
        assertTrue(displayBounds.width() > displayBounds.height());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Activity bounds should respect maximum aspect ratio for activity.
        assertEquals(displayBounds.height(), activityBounds.height());
        assertEquals((int) Math.rint(displayBounds.height()
                        / mActivity.info.getMaxAspectRatio()),
                activityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppWithAspectRatioOverride() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        final float fixedOrientationLetterboxAspectRatio = 1.1f;
        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(
                fixedOrientationLetterboxAspectRatio);
        prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_PORTRAIT, /* isUnresizable= */ false);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // Display shouldn't be rotated.
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED,
                mActivity.mDisplayContent.getLastOrientation());
        assertTrue(displayBounds.width() > displayBounds.height());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Activity bounds should respect aspect ratio override for fixed orientation letterbox.
        assertEquals(displayBounds.height(), activityBounds.height());
        assertEquals((int) Math.rint(displayBounds.height() / fixedOrientationLetterboxAspectRatio),
                activityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_unresizableWithCorrespondingMinAspectRatio() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        final float fixedOrientationLetterboxAspectRatio = 1.1f;
        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(
                fixedOrientationLetterboxAspectRatio);
        mActivity.mWmService.mLetterboxConfiguration.setDefaultMinAspectRatioForUnresizableApps(
                1.5f);
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // Display shouldn't be rotated.
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED,
                mActivity.mDisplayContent.getLastOrientation());
        assertTrue(displayBounds.width() > displayBounds.height());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Letterbox logic should use config_letterboxDefaultMinAspectRatioForUnresizableApps over
        // config_fixedOrientationLetterboxAspectRatio.
        assertEquals(displayBounds.height(), activityBounds.height());
        final float defaultAspectRatio = mActivity.mWmService.mLetterboxConfiguration
                .getDefaultMinAspectRatioForUnresizableApps();
        assertEquals(displayBounds.height() / defaultAspectRatio, activityBounds.width(), 0.5);
    }

    @Test
    public void testSplitAspectRatioForUnresizablePortraitApps() {
        // Set up a display in landscape and ignoring orientation request.
        int screenWidth = 1600;
        int screenHeight = 1400;
        setUpDisplaySizeWithApp(screenWidth, screenHeight);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration
                        .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);

        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        // Checking that there is no size compat mode.
        assertFitted();

        assertEquals(displayBounds.height(), activityBounds.height());
        assertTrue(activityBounds.width() < displayBounds.width() / 2);

        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
        organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(screenWidth), screenHeight);
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
        // Checking that there is no size compat mode.
        assertFitted();
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN})
    public void testOverrideSplitScreenAspectRatioForUnresizablePortraitApps() {
        final int displayWidth = 1400;
        final int displayHeight = 1600;
        setUpDisplaySizeWithApp(displayWidth, displayHeight);
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setMinAspectRatio(1.1f)
                .setUid(android.os.Process.myUid())
                .build();
        // Setup Letterbox Configuration
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        activity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.5f);
        // Non-resizable portrait activity
        prepareUnresizable(activity, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        float expectedAspectRatio = 1f * displayWidth / getExpectedSplitSize(displayHeight);
        final Rect afterBounds = activity.getBounds();
        final float afterAspectRatio = (float) (afterBounds.height()) / afterBounds.width();
        Assert.assertEquals(expectedAspectRatio, afterAspectRatio, 0.001f);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN})
    public void testOverrideSplitScreenAspectRatioForUnresizablePortraitAppsFromLandscape() {
        final int displayWidth = 1600;
        final int displayHeight = 1400;
        setUpDisplaySizeWithApp(displayWidth, displayHeight);
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setMinAspectRatio(1.1f)
                .setUid(android.os.Process.myUid())
                .build();
        // Setup Letterbox Configuration
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        activity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.5f);
        // Non-resizable portrait activity
        prepareUnresizable(activity, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        float expectedAspectRatio = 1f * displayHeight / getExpectedSplitSize(displayWidth);
        final Rect afterBounds = activity.getBounds();
        final float afterAspectRatio = (float) (afterBounds.height()) / afterBounds.width();
        Assert.assertEquals(expectedAspectRatio, afterAspectRatio, 0.001f);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN})
    @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY})
    public void testOverrideSplitScreenAspectRatioForUnresizableLandscapeApps() {
        final int displayWidth = 1400;
        final int displayHeight = 1600;
        setUpDisplaySizeWithApp(displayWidth, displayHeight);
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setMinAspectRatio(1.1f)
                .setUid(android.os.Process.myUid())
                .build();
        // Setup Letterbox Configuration
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        activity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.5f);
        // Non-resizable portrait activity
        prepareUnresizable(activity, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        float expectedAspectRatio = 1f * displayWidth / getExpectedSplitSize(displayHeight);
        final Rect afterBounds = activity.getBounds();
        final float afterAspectRatio = (float) (afterBounds.width()) / afterBounds.height();
        Assert.assertEquals(expectedAspectRatio, afterAspectRatio, 0.001f);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN})
    @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY})
    public void testOverrideSplitScreenAspectRatioForUnresizableLandscapeAppsFromLandscape() {
        final int displayWidth = 1600;
        final int displayHeight = 1400;
        setUpDisplaySizeWithApp(displayWidth, displayHeight);
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setMinAspectRatio(1.1f)
                .setUid(android.os.Process.myUid())
                .build();
        // Setup Letterbox Configuration
        activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        activity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.5f);
        // Non-resizable portrait activity
        prepareUnresizable(activity, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        float expectedAspectRatio = 1f * displayHeight / getExpectedSplitSize(displayWidth);
        final Rect afterBounds = activity.getBounds();
        final float afterAspectRatio = (float) (afterBounds.width()) / afterBounds.height();
        Assert.assertEquals(expectedAspectRatio, afterAspectRatio, 0.001f);
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN})
    public void testOverrideMinAspectRatioExcludePortraitFullscreen() {
        setUpDisplaySizeWithApp(2600, 1600);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.33f);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        // Non-resizable portrait activity
        prepareUnresizable(activity, 0f, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        // At first, OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_FULLSCREEN does not apply, because the
        // display is in landscape
        assertEquals(1600, activity.getBounds().height());
        assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                activity.getBounds().width(), 0.5);

        rotateDisplay(activity.mDisplayContent, ROTATION_90);
        prepareUnresizable(activity, /* maxAspect */ 0, SCREEN_ORIENTATION_PORTRAIT);

        // Now the display is in portrait fullscreen, so the override is applied making the content
        // fullscreen
        assertEquals(activity.getBounds(), activity.mDisplayContent.getBounds());
    }

    @Test
    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN})
    public void testOverrideMinAspectRatioExcludePortraitFullscreenNotApplied() {
        // In this test, the activity is not in fullscreen, so the override is not applied
        setUpDisplaySizeWithApp(2600, 1600);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.33f);

        // Create a size compat activity on the same task.
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();

        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, activity.getDisplayContent());

        // Move first activity to split screen which takes half of the screen.
        organizer.mPrimary.setBounds(0, 0, 1300, 1600);
        organizer.putTaskToPrimary(mTask, true);

        // Non-resizable portrait activity
        prepareUnresizable(activity, /* maxAspect */ 0, SCREEN_ORIENTATION_PORTRAIT);

        // OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_FULLSCREEN does not apply here because the
        // display is not in fullscreen, so OVERRIDE_MIN_ASPECT_RATIO_LARGE applies instead
        assertEquals(1600, activity.getBounds().height());
        assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                activity.getBounds().width(), 0.5);
    }

    @Test
    public void testSplitAspectRatioForUnresizableLandscapeApps() {
        // Set up a display in portrait and ignoring orientation request.
        int screenWidth = 1400;
        int screenHeight = 1600;
        setUpDisplaySizeWithApp(screenWidth, screenHeight);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration
                        .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);

        mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect activityBounds = new Rect(mActivity.getBounds());

        // App should launch in fixed orientation letterbox.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        // Checking that there is no size compat mode.
        assertFitted();

        assertEquals(displayBounds.width(), activityBounds.width());
        assertTrue(activityBounds.height() < displayBounds.height() / 2);

        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
        organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
        // Checking that there is no size compat mode.
        assertFitted();
    }

    @Test
    public void
            testDisplayIgnoreOrientationRequest_orientationLetterboxBecameSizeCompatAfterRotate() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app without max aspect.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);

        final Rect activityBounds = new Rect(mActivity.getBounds());

        // Rotate display to portrait.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect newActivityBounds = new Rect(mActivity.getBounds());
        assertTrue(displayBounds.width() < displayBounds.height());

        // App should be in size compat.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertScaled();
        assertEquals(activityBounds.width(), newActivityBounds.width());
        assertEquals(activityBounds.height(), newActivityBounds.height());
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_sizeCompatAfterRotate() {
        // Set up a display in portrait and ignoring orientation request.
        setUpDisplaySizeWithApp(1400, 2800);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app without max aspect.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);

        // App should launch in fullscreen.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        // Activity inherits max bounds from TaskDisplayArea.
        assertMaxBoundsInheritDisplayAreaBounds();

        // Rotate display to landscape.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        final Rect rotatedDisplayBounds = new Rect(mActivity.mDisplayContent.getBounds());
        final Rect rotatedActivityBounds = new Rect(mActivity.getBounds());
        assertTrue(rotatedDisplayBounds.width() > rotatedDisplayBounds.height());

        // App should be in size compat.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertScaled();
        assertThat(mActivity.inSizeCompatMode()).isTrue();
        assertActivityMaxBoundsSandboxed();

        // App bounds should be 700x1400 with the ratio as the display.
        assertEquals(rotatedDisplayBounds.height(), rotatedActivityBounds.height());
        assertEquals(rotatedDisplayBounds.height() * rotatedDisplayBounds.height()
                        / rotatedDisplayBounds.width(), rotatedActivityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_newLaunchedOrientationAppInLetterbox() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        final DisplayContent display = mActivity.mDisplayContent;
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app without max aspect.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);

        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Launch another portrait fixed app.
        spyOn(mTask);
        setBooted(display.mWmService.mAtmService);
        final ActivityRecord newActivity = new ActivityBuilder(display.mWmService.mAtmService)
                .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
                .setTask(mTask)
                .build();

        // Update with new activity requested orientation and recompute bounds with no previous
        // size compat cache.
        verify(mTask).onDescendantOrientationChanged(same(newActivity));

        final Rect displayBounds = new Rect(display.getBounds());
        final Rect taskBounds = new Rect(mTask.getBounds());
        final Rect newActivityBounds = new Rect(newActivity.getBounds());

        // Task and display bounds should be equal while activity should be letterboxed and
        // has 700x1400 bounds with the ratio as the display.
        assertTrue(newActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(newActivity.inSizeCompatMode());
        // Activity max bounds are sandboxed due to size compat mode.
        assertThat(newActivity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(newActivity.getWindowConfiguration().getBounds());
        assertEquals(taskBounds, displayBounds);
        assertEquals(displayBounds.height(), newActivityBounds.height());
        assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
                newActivityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_orientationChangedToUnspecified() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        final DisplayContent display = mActivity.mDisplayContent;
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app without max aspect.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);

        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);

        assertTrue(mActivity.inSizeCompatMode());
        // We should remember the original orientation.
        assertEquals(mActivity.getResolvedOverrideConfiguration().orientation,
                Configuration.ORIENTATION_PORTRAIT);
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_newLaunchedMaxAspectApp() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        final DisplayContent display = mActivity.mDisplayContent;
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app without max aspect.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);

        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Launch another portrait fixed app with max aspect ratio as 1.3.
        spyOn(mTask);
        setBooted(display.mWmService.mAtmService);
        final ActivityRecord newActivity = new ActivityBuilder(display.mWmService.mAtmService)
                .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
                .setMaxAspectRatio(1.3f)
                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
                .setTask(mTask)
                .build();

        // Update with new activity requested orientation and recompute bounds with no previous
        // size compat cache.
        verify(mTask).onDescendantOrientationChanged(same(newActivity));

        final Rect displayBounds = new Rect(display.getBounds());
        final Rect taskBounds = new Rect(mTask.getBounds());
        final Rect newActivityBounds = new Rect(newActivity.getBounds());

        // Task bounds should fill parent bounds.
        assertEquals(displayBounds, taskBounds);

        // Prior and new activity max bounds are sandboxed due to letterbox.
        assertThat(newActivity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(newActivityBounds);
        assertActivityMaxBoundsSandboxed();

        // Activity bounds should be (1400 / 1.3 = 1076)x1400 with the app requested ratio.
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(newActivity.inSizeCompatMode());
        assertEquals(displayBounds.height(), newActivityBounds.height());
        assertEquals((long) Math.rint(newActivityBounds.height()
                        / newActivity.info.getMaxAspectRatio()),
                newActivityBounds.width());
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_pausedAppNotLostSizeCompat() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        final DisplayContent display = mActivity.mDisplayContent;
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
        clearInvocations(mActivity);

        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());

        // Rotate display to portrait.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        // App should be in size compat.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertScaled();
        assertThat(mActivity.inSizeCompatMode()).isTrue();
        // Activity max bounds are sandboxed due to size compat mode.
        assertActivityMaxBoundsSandboxed();

        final Rect activityBounds = new Rect(mActivity.getBounds());
        mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);

        // App still in size compat, and the bounds don't change.
        verify(mActivity, never()).clearSizeCompatMode();
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertScaled();
        assertEquals(activityBounds, mActivity.getBounds());
        // Activity max bounds are sandboxed due to size compat.
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testDisplayIgnoreOrientationRequest_rotated180_notInSizeCompat() {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        final DisplayContent display = mActivity.mDisplayContent;
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Portrait fixed app.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);

        // In fixed orientation letterbox
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed();

        // Rotate display to portrait.
        rotateDisplay(display, ROTATION_90);

        // App should be in size compat.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertScaled();
        assertActivityMaxBoundsSandboxed();

        // Rotate display to landscape.
        rotateDisplay(display, ROTATION_180);

        // In activity letterbox
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testDisplayIgnoreOrientationRequestWithInsets_rotated180_notInSizeCompat() {
        // Set up a display in portrait with display cutout and ignoring orientation request.
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1400, 2800)
                .setNotch(75)
                .build();
        setUpApp(display);
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        // Landscape fixed app.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);

        // In fixed orientation letterbox
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed();

        // Rotate display to landscape.
        rotateDisplay(display, ROTATION_90);

        // App should be in size compat.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertScaled();
        assertActivityMaxBoundsSandboxed();

        // Rotate display to portrait.
        rotateDisplay(display, ROTATION_180);

        // In fixed orientation letterbox
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testSandboxDisplayApis_unresizableAppNotSandboxed() {
        // Set up a display in landscape with an unresizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setSandboxDisplayApis(false /* sandboxDisplayApis */);
        prepareUnresizable(mActivity, 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
        assertFitted();

        // Activity max bounds not be sandboxed since sandboxing is disabled.
        assertMaxBoundsInheritDisplayAreaBounds();
    }

    @Test
    public void testSandboxDisplayApis_unresizableAppSandboxed() {
        // Set up a display in landscape with an unresizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setSandboxDisplayApis(true /* sandboxDisplayApis */);
        prepareUnresizable(mActivity, 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
        assertFitted();

        // Activity max bounds should be sandboxed since sandboxing is enabled.
        assertActivityMaxBoundsSandboxed();
    }

    @Test
    public void testResizableApp_notSandboxed() {
        // Set up a display in landscape with a fully resizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        prepareLimitedBounds(mActivity, /* maxAspect= */ -1,
                SCREEN_ORIENTATION_UNSPECIFIED, /* isUnresizable= */ false);
        assertFitted();

        // Activity max bounds not be sandboxed since app is fully resizable.
        assertMaxBoundsInheritDisplayAreaBounds();
    }

    @Test
    public void testResizableMaxAspectApp_notSandboxed() {
        // Set up a display in landscape with a fully resizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        prepareLimitedBounds(mActivity, /* maxAspect= */ 1,
                SCREEN_ORIENTATION_UNSPECIFIED, /* isUnresizable= */ false);
        assertFitted();

        // Activity max bounds not be sandboxed since app is fully resizable.
        assertMaxBoundsInheritDisplayAreaBounds();
    }

    @Test
    public void testResizableOrientationRequestApp_notSandboxed() {
        // Set up a display in landscape with a fully resizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        prepareLimitedBounds(mActivity, /* maxAspect= */ -1,
                SCREEN_ORIENTATION_PORTRAIT, /* isUnresizable= */ false);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        assertFitted();

        // Activity max bounds not be sandboxed since app is fully resizable.
        assertMaxBoundsInheritDisplayAreaBounds();
    }

    @Test
    public void testResizableMaxAspectOrientationRequestApp_notSandboxed() {
        // Set up a display in landscape with a fully resizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        prepareLimitedBounds(mActivity, /* maxAspect= */ 1,
                SCREEN_ORIENTATION_PORTRAIT, /* isUnresizable= */ false);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        assertFitted();

        // Activity max bounds not be sandboxed since app is fully resizable.
        assertMaxBoundsInheritDisplayAreaBounds();
    }

    @Test
    public void testUnresizableApp_isSandboxed() {
        // Set up a display in landscape with a fully resizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        prepareLimitedBounds(mActivity, /* maxAspect= */ -1,
                SCREEN_ORIENTATION_UNSPECIFIED, /* isUnresizable= */ true);
        assertFitted();

        // Activity max bounds are sandboxed since app may enter size compat mode.
        assertActivityMaxBoundsSandboxed();
        assertFalse(mActivity.inSizeCompatMode());
    }

    @Test
    public void testUnresizableMaxAspectApp_isSandboxed() {
        // Set up a display in landscape with a fully resizable app.
        setUpDisplaySizeWithApp(2500, 1000);
        prepareLimitedBounds(mActivity, /* maxAspect= */ 1,
                SCREEN_ORIENTATION_UNSPECIFIED, /* isUnresizable= */ true);
        assertFitted();

        // Activity max bounds are sandboxed since app may enter size compat mode.
        assertActivityMaxBoundsSandboxed();
        assertFalse(mActivity.inSizeCompatMode());
        assertTrue(mActivity.shouldCreateCompatDisplayInsets());

        // Resize display to half the width.
        resizeDisplay(mActivity.getDisplayContent(), 500, 1000);

        // Activity now in size compat mode.
        assertActivityMaxBoundsSandboxed();
        assertTrue(mActivity.inSizeCompatMode());
    }

    @Test
    public void testTaskDisplayAreaNotFillDisplay() {
        setUpDisplaySizeWithApp(1400, 2800);
        final DisplayContent display = mActivity.mDisplayContent;
        final TaskDisplayArea taskDisplayArea = mActivity.getDisplayArea();
        taskDisplayArea.setBounds(0, 0, 1000, 2400);

        // Portrait fixed app.
        prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);

        final Rect displayBounds = new Rect(display.getBounds());
        assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
        assertEquals(2800, displayBounds.width());
        assertEquals(1400, displayBounds.height());
        Rect displayAreaBounds = new Rect(0, 0, 2400, 1000);
        taskDisplayArea.setBounds(displayAreaBounds);

        final Rect activityBounds = new Rect(mActivity.getBounds());
        assertFalse(mActivity.inSizeCompatMode());
        assertEquals(2400, activityBounds.width());
        assertEquals(1000, activityBounds.height());
        // Task and activity maximum bounds inherit from TaskDisplayArea bounds.
        assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(displayAreaBounds);
        assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(displayAreaBounds);
    }

    @Test
    public void testSupportsNonResizableInSplitScreen_letterboxForDifferentOrientation() {
        // Support non resizable in multi window
        mAtm.mDevEnableNonResizableMultiWindow = true;
        setUpDisplaySizeWithApp(1000, 2800);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        // Non-resizable landscape activity
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
        final Rect originalBounds = new Rect(mActivity.getBounds());

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP,
                false /*moveParents*/, "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 1400);
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());

        // Non-resizable activity in size compat mode
        assertScaled();
        final Rect newBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(originalBounds.width(), newBounds.width());
        assertEquals(originalBounds.height(), newBounds.height());
        assertActivityMaxBoundsSandboxed();

        recomputeNaturalConfigurationOfUnresizableActivity();

        // Split screen is also in portrait [1000,1400], so activity should be in fixed orientation
        // letterbox.
        assertEquals(ORIENTATION_PORTRAIT, mTask.getConfiguration().orientation);
        assertEquals(ORIENTATION_LANDSCAPE, mActivity.getConfiguration().orientation);
        assertFitted();
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertActivityMaxBoundsSandboxed();

        // Letterbox should fill the gap between the split screen and the letterboxed activity.
        assertLetterboxSurfacesDrawnBetweenActivityAndParentBounds(organizer.mPrimary.getBounds());
    }

    @Test
    public void testResizableFixedOrientationAppInSplitScreen_letterboxForDifferentOrientation() {
        setUpDisplaySizeWithApp(1000, 2800);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        // Resizable landscape-only activity.
        prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_LANDSCAPE, /* isUnresizable= */ false);

        final Rect originalBounds = new Rect(mActivity.getBounds());

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 1400);
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());

        // Resizable activity is not in size compat mode but in the letterbox for fixed orientation.
        assertFitted();
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void testSupportsNonResizableInSplitScreen_aspectRatioLetterboxInSameOrientation() {
        // Support non resizable in multi window
        mAtm.mDevEnableNonResizableMultiWindow = true;
        setUpDisplaySizeWithApp(1000, 2800);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        // Non-resizable portrait activity
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
        final Rect originalBounds = new Rect(mActivity.getBounds());

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP,
                false /*moveParents*/, "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 1400);
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());

        // Non-resizable activity in size compat mode
        assertScaled();
        final Rect newBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(originalBounds.width(), newBounds.width());
        assertEquals(originalBounds.height(), newBounds.height());
        assertActivityMaxBoundsSandboxed();

        recomputeNaturalConfigurationOfUnresizableActivity();

        // Split screen is also in portrait [1000,1400], which meets the activity request. It should
        // sandbox to the activity bounds for non-resizable.
        assertEquals(ORIENTATION_PORTRAIT, mTask.getConfiguration().orientation);
        assertEquals(ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
        assertFitted();
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertActivityMaxBoundsSandboxed();

        // Activity bounds fill split screen.
        final Rect primarySplitBounds = new Rect(organizer.mPrimary.getBounds());
        final Rect letterboxedBounds = new Rect(mActivity.getBounds());
        assertEquals(primarySplitBounds, letterboxedBounds);
    }

    @Test
    public void testSupportsNonResizableInSplitScreen_letterboxForAspectRatioRestriction() {
        // Support non resizable in multi window
        mAtm.mDevEnableNonResizableMultiWindow = true;
        setUpDisplaySizeWithApp(/* dw */ 1000, /* dh */ 2800);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);

        // Bounds are letterboxed to respect the provided max aspect ratio.
        assertEquals(mActivity.getBounds(), new Rect(0, 0, 1000, 1100));

        // Move activity to split screen which has landscape size.
        mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents */ false, "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 800);

        // Non-resizable activity should be in size compat mode.
        assertScaled();
        assertEquals(mActivity.getBounds(), new Rect(60, 0, 940, 800));

        recomputeNaturalConfigurationOfUnresizableActivity();

        // Activity should still be letterboxed but not in the size compat mode.
        assertFitted();
        assertEquals(mActivity.getBounds(), new Rect(60, 0, 940, 800));

        // Letterbox should fill the gap between the split screen and the letterboxed activity.
        assertLetterboxSurfacesDrawnBetweenActivityAndParentBounds(organizer.mPrimary.getBounds());
    }

    @Test
    public void testLetterboxDetailsForStatusBar_noLetterbox() {
        setUpDisplaySizeWithApp(2800, 1000);
        addStatusBar(mActivity.mDisplayContent);
        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        StatusBarManagerInternal statusBar = displayPolicy.getStatusBarManagerInternal();
        // We should get a null LetterboxDetails object as there is no letterboxed activity, so
        // nothing will get passed to SysUI
        verify(statusBar, never()).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), isNull());

    }

    @Test
    public void testLetterboxDetailsForStatusBar_letterboxedForMaxAspectRatio() {
        setUpDisplaySizeWithApp(2800, 1000);
        addStatusBar(mActivity.mDisplayContent);
        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails
        // Prepare unresizable activity with max aspect ratio
        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);
        // Refresh the letterbox
        mActivity.mRootWindowContainer.performSurfacePlacement();

        Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(mBounds, new Rect(850, 0, 1950, 1000));

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        LetterboxDetails[] expectedLetterboxDetails = {new LetterboxDetails(
                mBounds,
                mActivity.getDisplayContent().getBounds(),
                mActivity.findMainWindow().mAttrs.insetsFlags.appearance
        )};

        // Check that letterboxDetails actually gets passed to SysUI
        StatusBarManagerInternal statusBar = displayPolicy.getStatusBarManagerInternal();
        verify(statusBar).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), eq(expectedLetterboxDetails));
    }

    @Test
    public void testLetterboxDetailsForStatusBar_letterboxNotOverlappingStatusBar() {
        // Align to center so that we don't overlap with the status bar
        mAtm.mWindowManager.mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(0.5f);
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2800)
                .setNotch(100)
                .build();
        setUpApp(display);
        TestWindowState statusBar = addStatusBar(mActivity.mDisplayContent);
        spyOn(statusBar);
        doReturn(new Rect(0, 0, statusBar.mRequestedWidth, statusBar.mRequestedHeight))
                .when(statusBar).getFrame();
        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails
        // Prepare unresizable activity with max aspect ratio
        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);
        // Refresh the letterbox
        mActivity.mRootWindowContainer.performSurfacePlacement();

        Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(mBounds, new Rect(0, 900, 1000, 2000));

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        LetterboxDetails[] expectedLetterboxDetails = {new LetterboxDetails(
                mBounds,
                mActivity.getDisplayContent().getBounds(),
                mActivity.findMainWindow().mAttrs.insetsFlags.appearance
        )};

        // Check that letterboxDetails actually gets passed to SysUI
        StatusBarManagerInternal statusBarManager = displayPolicy.getStatusBarManagerInternal();
        verify(statusBarManager).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), eq(expectedLetterboxDetails));
    }

    @Test
    public void testSplitScreenLetterboxDetailsForStatusBar_twoLetterboxedApps() {
        mAtm.mDevEnableNonResizableMultiWindow = true;
        setUpDisplaySizeWithApp(2800, 1000);
        addStatusBar(mActivity.mDisplayContent);
        // Create another task for the second activity
        final Task newTask = new TaskBuilder(mSupervisor).setDisplay(mActivity.getDisplayContent())
                .setCreateActivity(true).build();
        ActivityRecord newActivity = newTask.getTopNonFinishingActivity();

        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        // Move first activity to split screen which takes half of the screen.
        organizer.mPrimary.setBounds(0, 0, 1400, 1000);
        organizer.putTaskToPrimary(mTask, true);
        // Move second activity to split screen which takes half of the screen.
        organizer.mSecondary.setBounds(1400, 0, 2800, 1000);
        organizer.putTaskToSecondary(newTask, true);

        addWindowToActivity(mActivity); // Add a window to the activity so that we can get an
        // appearance inside letterboxDetails
        // Prepare unresizable activity with max aspect ratio
        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);
        addWindowToActivity(newActivity);
        prepareUnresizable(newActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);

        // Refresh the letterboxes
        newActivity.mRootWindowContainer.performSurfacePlacement();

        Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        assertEquals(mBounds, new Rect(150, 0, 1250, 1000));
        final Rect newBounds = new Rect(newActivity.getWindowConfiguration().getBounds());
        assertEquals(newBounds, new Rect(1550, 0, 2650, 1000));

        DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy();
        LetterboxDetails[] expectedLetterboxDetails = { new LetterboxDetails(
                mBounds,
                organizer.mPrimary.getBounds(),
                mActivity.findMainWindow().mAttrs.insetsFlags.appearance
        ), new LetterboxDetails(
                newBounds,
                organizer.mSecondary.getBounds(),
                newActivity.findMainWindow().mAttrs.insetsFlags.appearance
        )};

        // Check that letterboxDetails actually gets passed to SysUI
        StatusBarManagerInternal statusBar = displayPolicy.getStatusBarManagerInternal();
        verify(statusBar).onSystemBarAttributesChanged(anyInt(), anyInt(),
                any(), anyBoolean(), anyInt(),
                any(InsetsVisibilities.class), isNull(), eq(expectedLetterboxDetails));
    }

    private void recomputeNaturalConfigurationOfUnresizableActivity() {
        // Recompute the natural configuration of the non-resizable activity and the split screen.
        mActivity.clearSizeCompatMode();

        // Draw letterbox.
        mActivity.setVisible(false);
        mActivity.mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_OPEN);
        mActivity.mDisplayContent.mOpeningApps.add(mActivity);
        addWindowToActivity(mActivity);
        mActivity.mRootWindowContainer.performSurfacePlacement();
    }

    private void assertLetterboxSurfacesDrawnBetweenActivityAndParentBounds(Rect parentBounds) {
        // Letterbox should fill the gap between the parent bounds and the letterboxed activity.
        final Rect letterboxedBounds = new Rect(mActivity.getBounds());
        assertTrue(parentBounds.contains(letterboxedBounds));
        assertEquals(new Rect(letterboxedBounds.left - parentBounds.left,
                letterboxedBounds.top - parentBounds.top,
                parentBounds.right - letterboxedBounds.right,
                parentBounds.bottom - letterboxedBounds.bottom),
                mActivity.getLetterboxInsets());
    }

    @Test
    public void testUpdateResolvedBoundsHorizontalPosition_left() {
        // Display configured as (2800, 1400).
        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxHorizontalPositionMultiplier */ 0.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(0, 0, 700, 1400),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(0, 0, 700, 1400),
                // After the display is resized to (700, 1400).
                /* sizeCompatScaled */ new Rect(0, 0, 350, 700));
    }

    @Test
    public void testUpdateResolvedBoundsHorizontalPosition_center() {
        // Display configured as (2800, 1400).
        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxHorizontalPositionMultiplier */ 0.5f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(1050, 0, 1750, 1400),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(350, 0, 1050, 1400),
                // After the display is resized to (700, 1400).
                /* sizeCompatScaled */ new Rect(525, 0, 875, 700));
    }

    @Test
    public void testUpdateResolvedBoundsHorizontalPosition_invalidMultiplier_defaultToCenter() {
        // Display configured as (2800, 1400).

        // Below 0.0.
        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxHorizontalPositionMultiplier */ -1.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(1050, 0, 1750, 1400),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(350, 0, 1050, 1400),
                // After the display is resized to (700, 1400).
                /* sizeCompatScaled */ new Rect(525, 0, 875, 700));

        // Above 1.0
        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxHorizontalPositionMultiplier */ 2.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(1050, 0, 1750, 1400),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(350, 0, 1050, 1400),
                // After the display is resized to (700, 1400).
                /* sizeCompatScaled */ new Rect(525, 0, 875, 700));
    }

    @Test
    public void testUpdateResolvedBoundsHorizontalPosition_right() {
        // Display configured as (2800, 1400).
        assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxHorizontalPositionMultiplier */ 1.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(2100, 0, 2800, 1400),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(700, 0, 1400, 1400),
                // After the display is resized to (700, 1400).
                /* sizeCompatScaled */ new Rect(1050, 0, 1400, 700));
    }

    private void assertHorizontalPositionForDifferentDisplayConfigsForPortraitActivity(
            float letterboxHorizontalPositionMultiplier, Rect fixedOrientationLetterbox,
            Rect sizeCompatUnscaled, Rect sizeCompatScaled) {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
                letterboxHorizontalPositionMultiplier);
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
        assertEquals(fixedOrientationLetterbox, mActivity.getBounds());
        // Rotate to put activity in size compat mode.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
        assertTrue(mActivity.inSizeCompatMode());
        // Activity is in size compat mode but not scaled.
        assertEquals(sizeCompatUnscaled, mActivity.getBounds());
        // Force activity to scaled down for size compat mode.
        resizeDisplay(mTask.mDisplayContent, 700, 1400);
        assertTrue(mActivity.inSizeCompatMode());
        assertScaled();
        assertEquals(sizeCompatScaled, mActivity.getBounds());
    }

    @Test
    public void testApplyAspectRatio_activityAlignWithParentAppVertical() {
        // The display's app bounds will be (0, 100, 1000, 2350)
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500)
                .setCanRotate(false)
                .setCutout(0, 100, 0, 150)
                .build();

        setUpApp(display);
        prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
        // The activity height is 2100 and the display's app bounds height is 2250, so the activity
        // can be aligned inside parentAppBounds
        assertEquals(mActivity.getBounds(), new Rect(0, 0, 1000, 2200));
    }
    @Test
    public void testApplyAspectRatio_activityCannotAlignWithParentAppVertical() {
        // The display's app bounds will be (0, 100, 1000, 2150)
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2300)
                .setCanRotate(false)
                .setCutout(0, 100, 0, 150)
                .build();

        setUpApp(display);
        prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
        // The activity height is 2100 and the display's app bounds height is 2050, so the activity
        // cannot be aligned inside parentAppBounds and it will fill the parentBounds of the display
        assertEquals(mActivity.getBounds(), display.getBounds());
    }

    @Test
    public void testApplyAspectRatio_activityAlignWithParentAppHorizontal() {
        // The display's app bounds will be (100, 0, 2350, 1000)
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2500, 1000)
                .setCanRotate(false)
                .setCutout(100, 0, 150, 0)
                .build();

        setUpApp(display);
        prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
        // The activity width is 2100 and the display's app bounds width is 2250, so the activity
        // can be aligned inside parentAppBounds
        assertEquals(mActivity.getBounds(), new Rect(175, 0, 2275, 1000));
    }
    @Test
    public void testApplyAspectRatio_activityCannotAlignWithParentAppHorizontal() {
        // The display's app bounds will be (100, 0, 2150, 1000)
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2300, 1000)
                .setCanRotate(false)
                .setCutout(100, 0, 150, 0)
                .build();

        setUpApp(display);
        prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED);
        // The activity width is 2100 and the display's app bounds width is 2050, so the activity
        // cannot be aligned inside parentAppBounds and it will fill the parentBounds of the display
        assertEquals(mActivity.getBounds(), display.getBounds());
    }

    @Test
    public void testUpdateResolvedBoundsHorizontalPosition_activityFillParentWidth() {
        // When activity width equals parent width, multiplier shouldn't have any effect.
        assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxHorizontalPositionMultiplier */ 0.0f);
        assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxHorizontalPositionMultiplier */ 0.5f);
        assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxHorizontalPositionMultiplier */ 1.0f);
    }

    @Test
    public void testUpdateResolvedBoundsVerticalPosition_top() {
        // Display configured as (1400, 2800).
        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxVerticalPositionMultiplier */ 0.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(0, 0, 1400, 700),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(700, 0, 2100, 700),
                // After the display is resized to (1400, 700).
                /* sizeCompatScaled */ new Rect(0, 0, 700, 350));
    }

    @Test
    public void testUpdateResolvedBoundsVerticalPosition_center() {
        // Display configured as (1400, 2800).
        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxVerticalPositionMultiplier */ 0.5f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(0, 1050, 1400, 1750),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(700, 350, 2100, 1050),
                // After the display is resized to (1400, 700).
                /* sizeCompatScaled */ new Rect(0, 525, 700, 875));
    }

    @Test
    public void testUpdateResolvedBoundsVerticalPosition_invalidMultiplier_defaultToCenter() {
        // Display configured as (1400, 2800).

        // Below 0.0.
        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxVerticalPositionMultiplier */ -1.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(0, 1050, 1400, 1750),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(700, 350, 2100, 1050),
                // After the display is resized to (1400, 700).
                /* sizeCompatScaled */ new Rect(0, 525, 700, 875));

        // Above 1.0
        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxVerticalPositionMultiplier */ 2.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(0, 1050, 1400, 1750),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(700, 350, 2100, 1050),
                // After the display is resized to (1400, 700).
                /* sizeCompatScaled */ new Rect(0, 525, 700, 875));
    }

    @Test
    public void testUpdateResolvedBoundsVerticalPosition_bottom() {
        // Display configured as (1400, 2800).
        assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
                /* letterboxVerticalPositionMultiplier */ 1.0f,
                // At launch.
                /* fixedOrientationLetterbox */ new Rect(0, 2100, 1400, 2800),
                // After 90 degree rotation.
                /* sizeCompatUnscaled */ new Rect(700, 700, 2100, 1400),
                // After the display is resized to (1400, 700).
                /* sizeCompatScaled */ new Rect(0, 1050, 700, 1400));
    }

    @Test
    public void testUpdateResolvedBoundsPosition_alignToTop() {
        final int notchHeight = 100;
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2800)
                .setNotch(notchHeight)
                .build();
        setUpApp(display);

        // Prepare unresizable activity with max aspect ratio
        prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED);

        Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
        Rect appBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds());
        // The insets should be cut for aspect ratio and then added back because the appBounds
        // are aligned to the top of the parentAppBounds
        assertEquals(mBounds, new Rect(0, 0, 1000, 1200));
        assertEquals(appBounds, new Rect(0, notchHeight, 1000, 1200));
    }

    private void assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity(
            float letterboxVerticalPositionMultiplier, Rect fixedOrientationLetterbox,
            Rect sizeCompatUnscaled, Rect sizeCompatScaled) {
        // Set up a display in portrait and ignoring orientation request.
        setUpDisplaySizeWithApp(1400, 2800);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        mActivity.mWmService.mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(
                letterboxVerticalPositionMultiplier);
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);

        assertEquals(fixedOrientationLetterbox, mActivity.getBounds());

        // Rotate to put activity in size compat mode.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        assertTrue(mActivity.inSizeCompatMode());
        // Activity is in size compat mode but not scaled.
        assertEquals(sizeCompatUnscaled, mActivity.getBounds());

        // Force activity to scaled down for size compat mode.
        resizeDisplay(mTask.mDisplayContent, 1400, 700);

        assertTrue(mActivity.inSizeCompatMode());
        assertScaled();
        assertEquals(sizeCompatScaled, mActivity.getBounds());
    }

    @Test
    public void testUpdateResolvedBoundsVerticalPosition_activityFillParentHeight() {
        // When activity height equals parent height, multiplier shouldn't have any effect.
        assertVerticalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxVerticalPositionMultiplier */ 0.0f);
        assertVerticalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxVerticalPositionMultiplier */ 0.5f);
        assertVerticalPositionForDifferentDisplayConfigsForPortraitActivity(
                /* letterboxVerticalPositionMultiplier */ 1.0f);
    }

    @Test
    public void testAreBoundsLetterboxed_letterboxedForAspectRatio_returnsTrue() {
        setUpDisplaySizeWithApp(1000, 2500);

        assertFalse(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);

        prepareUnresizable(mActivity, /* maxAspect= */ 2, SCREEN_ORIENTATION_PORTRAIT);
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertTrue(mActivity.areBoundsLetterboxed());

        verifyLogAppCompatState(mActivity,
                APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO);

        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
        verifyLogAppCompatState(mActivity,
                APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE);
        rotateDisplay(mActivity.mDisplayContent, ROTATION_0);

        // After returning to the original rotation, bounds are computed in
        // ActivityRecord#resolveSizeCompatModeConfiguration because mCompatDisplayInsets aren't
        // null but activity doesn't enter size compat mode. Checking that areBoundsLetterboxed()
        // still returns true because of the aspect ratio restrictions.
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertTrue(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity,
                APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO);

        // After setting the visibility of the activity to false, areBoundsLetterboxed() still
        // returns true but the NOT_VISIBLE App Compat state is logged.
        mActivity.setVisibility(false);
        assertTrue(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_VISIBLE);
        mActivity.setVisibility(true);
        assertTrue(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity,
                APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO);
    }

    @Test
    public void testAreBoundsLetterboxed_letterboxedForFixedOrientation_returnsTrue() {
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        assertFalse(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
        assertTrue(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity,
                APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION);
    }

    @Test
    public void testAreBoundsLetterboxed_letterboxedForSizeCompat_returnsTrue() {
        setUpDisplaySizeWithApp(1000, 2500);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertFalse(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);

        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertTrue(mActivity.inSizeCompatMode());
        assertTrue(mActivity.areBoundsLetterboxed());
        verifyLogAppCompatState(mActivity,
                APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_SIZE_COMPAT_MODE);
    }

    @Test
    public void testIsEligibleForLetterboxEducation_educationNotEnabled_returnsFalse() {
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(false);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertFalse(mActivity.isEligibleForLetterboxEducation());
    }

    @Test
    public void testIsEligibleForLetterboxEducation_notEligibleForFixedOrientation_returnsFalse() {
        setUpDisplaySizeWithApp(1000, 2500);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(true);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertFalse(mActivity.isEligibleForLetterboxEducation());
    }

    @Test
    public void testIsEligibleForLetterboxEducation_windowingModeMultiWindow_returnsFalse() {
        // Support non resizable in multi window
        mAtm.mDevEnableNonResizableMultiWindow = true;
        setUpDisplaySizeWithApp(1000, 1200);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(true);
        final TestSplitOrganizer organizer =
                new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());

        // Non-resizable landscape activity
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
        final Rect originalBounds = new Rect(mActivity.getBounds());

        // Move activity to split screen which takes half of the screen.
        mTask.reparent(organizer.mPrimary, POSITION_TOP,
                false /*moveParents*/, "test");
        organizer.mPrimary.setBounds(0, 0, 1000, 600);

        assertFalse(mActivity.isEligibleForLetterboxEducation());
        assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
    }

    @Test
    public void testIsEligibleForLetterboxEducation_fixedOrientationLandscape_returnsFalse() {
        setUpDisplaySizeWithApp(1000, 2500);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(true);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);

        assertFalse(mActivity.isEligibleForLetterboxEducation());
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void testIsEligibleForLetterboxEducation_hasStartingWindow_returnsFalseUntilRemoved() {
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(true);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
        mActivity.mStartingData = mock(StartingData.class);
        mActivity.attachStartingWindow(
                createWindowState(new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING),
                        mActivity));

        assertFalse(mActivity.isEligibleForLetterboxEducation());

        // Verify that after removing the starting window isEligibleForLetterboxEducation returns
        // true and mTask.dispatchTaskInfoChangedIfNeeded is called.
        spyOn(mTask);
        mActivity.removeStartingWindow();

        assertTrue(mActivity.isEligibleForLetterboxEducation());
        verify(mTask).dispatchTaskInfoChangedIfNeeded(true);
    }

    @Test
    public void testIsEligibleForLetterboxEducation_hasStartingWindowAndEducationNotEnabled() {
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(false);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
        mActivity.mStartingData = mock(StartingData.class);
        mActivity.attachStartingWindow(
                createWindowState(new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING),
                        mActivity));

        assertFalse(mActivity.isEligibleForLetterboxEducation());

        // Verify that after removing the starting window isEligibleForLetterboxEducation still
        // returns false and mTask.dispatchTaskInfoChangedIfNeeded isn't called.
        spyOn(mTask);
        mActivity.removeStartingWindow();

        assertFalse(mActivity.isEligibleForLetterboxEducation());
        verify(mTask, never()).dispatchTaskInfoChangedIfNeeded(true);
    }

    @Test
    public void testIsEligibleForLetterboxEducation_letterboxedForFixedOrientation_returnsTrue() {
        setUpDisplaySizeWithApp(2500, 1000);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(true);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertTrue(mActivity.isEligibleForLetterboxEducation());
        assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void testIsEligibleForLetterboxEducation_sizeCompatAndEligibleForFixedOrientation() {
        setUpDisplaySizeWithApp(1000, 2500);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mActivity.mWmService.mLetterboxConfiguration.setIsEducationEnabled(true);

        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        assertTrue(mActivity.isEligibleForLetterboxEducation());
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertTrue(mActivity.inSizeCompatMode());
    }

    /**
     * Tests that all three paths in which aspect ratio logic can be applied yield the same
     * result, which is that aspect ratio is respected on app bounds. The three paths are
     * fixed orientation, no fixed orientation but fixed aspect ratio, and size compat mode.
     */
    @Test
    public void testAllAspectRatioLogicConsistent() {
        // Create display that has all stable insets and does not rotate. Make sure that status bar
        // height is greater than notch height so that stable bounds do not equal app bounds.
        final int notchHeight = 75;
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1080, 600)
                .setSystemDecorations(true).setNotch(notchHeight)
                .setStatusBarHeight(notchHeight + 20).setCanRotate(false).build();

        // Create task on test display.
        final Task task = new TaskBuilder(mSupervisor).setDisplay(display).build();

        // Target min aspect ratio must be larger than parent aspect ratio to be applied.
        final float targetMinAspectRatio = 3.0f;

        // Create fixed portait activity with min aspect ratio greater than parent aspect ratio.
        final ActivityRecord fixedOrientationActivity = new ActivityBuilder(mAtm)
                .setTask(task).setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
                .setMinAspectRatio(targetMinAspectRatio).build();
        final Rect fixedOrientationAppBounds = new Rect(fixedOrientationActivity.getConfiguration()
                .windowConfiguration.getAppBounds());

        // Create activity with no fixed orientation and min aspect ratio greater than parent aspect
        // ratio.
        final ActivityRecord minAspectRatioActivity = new ActivityBuilder(mAtm).setTask(task)
                .setMinAspectRatio(targetMinAspectRatio).build();
        final Rect minAspectRatioAppBounds = new Rect(minAspectRatioActivity.getConfiguration()
                .windowConfiguration.getAppBounds());

        // Create unresizeable fixed portait activity with min aspect ratio greater than parent
        // aspect ratio.
        final ActivityRecord sizeCompatActivity = new ActivityBuilder(mAtm)
                .setTask(task).setResizeMode(RESIZE_MODE_UNRESIZEABLE)
                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
                .setMinAspectRatio(targetMinAspectRatio).build();
        // Resize display running unresizeable activity to make it enter size compat mode.
        resizeDisplay(display, 1800, 1000);
        final Rect sizeCompatAppBounds = new Rect(sizeCompatActivity.getConfiguration()
                .windowConfiguration.getAppBounds());

        // Check that aspect ratio of app bounds is equal to the min aspect ratio.
        final float delta = 0.01f;
        assertEquals(targetMinAspectRatio, ActivityRecord
                .computeAspectRatio(fixedOrientationAppBounds), delta);
        assertEquals(targetMinAspectRatio, ActivityRecord
                .computeAspectRatio(minAspectRatioAppBounds), delta);
        assertEquals(targetMinAspectRatio, ActivityRecord
                .computeAspectRatio(sizeCompatAppBounds), delta);
    }

    @Test
    public void testClearSizeCompat_resetOverrideConfig() {
        final int origDensity = 480;
        final int newDensity = 520;
        final DisplayContent display = new TestDisplayContent.Builder(mAtm, 600, 800)
                .setDensityDpi(origDensity)
                .build();
        setUpApp(display);
        prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);

        // Activity should enter size compat with old density after display density change.
        display.setForcedDensity(newDensity, UserHandle.USER_CURRENT);

        assertScaled();
        assertEquals(origDensity, mActivity.getConfiguration().densityDpi);

        // Activity should exit size compat with new density.
        mActivity.clearSizeCompatMode();

        assertFitted();
        assertEquals(newDensity, mActivity.getConfiguration().densityDpi);
    }

    private int getExpectedSplitSize(int dimensionToSplit) {
        int dividerWindowWidth =
                mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.docked_stack_divider_thickness);
        int dividerInsets =
                mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.docked_stack_divider_insets);
        return (dimensionToSplit - (dividerWindowWidth - dividerInsets * 2)) / 2;
    }

    private void assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
            float letterboxHorizontalPositionMultiplier) {
        // Set up a display in landscape and ignoring orientation request.
        setUpDisplaySizeWithApp(2800, 1400);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
                letterboxHorizontalPositionMultiplier);
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
        assertFitted();
        // Rotate to put activity in size compat mode.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
        assertTrue(mActivity.inSizeCompatMode());
        // Activity is in size compat mode but not scaled.
        assertEquals(new Rect(0, 0, 1400, 700), mActivity.getBounds());
    }

    private void assertVerticalPositionForDifferentDisplayConfigsForPortraitActivity(
            float letterboxVerticalPositionMultiplier) {
        // Set up a display in portrait and ignoring orientation request.
        setUpDisplaySizeWithApp(1400, 2800);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);

        mActivity.mWmService.mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(
                letterboxVerticalPositionMultiplier);
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertFitted();

        // Rotate to put activity in size compat mode.
        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);

        assertTrue(mActivity.inSizeCompatMode());
        // Activity is in size compat mode but not scaled.
        assertEquals(new Rect(1050, 0, 1750, 1400), mActivity.getBounds());
    }

    private static WindowState addWindowToActivity(ActivityRecord activity) {
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        params.setFitInsetsSides(0);
        params.setFitInsetsTypes(0);
        final TestWindowState w = new TestWindowState(
                activity.mWmService, mock(Session.class), new TestIWindow(), params, activity);
        makeWindowVisible(w);
        w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
        activity.addWindow(w);
        return w;
    }

    private static TestWindowState addStatusBar(DisplayContent displayContent) {
        final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
        doReturn(true).when(displayPolicy).hasStatusBar();
        displayPolicy.onConfigurationChanged();

        final TestWindowToken token = createTestWindowToken(
                TYPE_STATUS_BAR, displayContent);
        final WindowManager.LayoutParams attrs =
                new WindowManager.LayoutParams(TYPE_STATUS_BAR);
        attrs.gravity = android.view.Gravity.TOP;
        attrs.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        attrs.setFitInsetsTypes(0 /* types */);
        final TestWindowState statusBar = new TestWindowState(
                displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
        token.addWindow(statusBar);
        statusBar.setRequestedSize(displayContent.mBaseDisplayWidth,
                SystemBarUtils.getStatusBarHeight(displayContent.getDisplayUiContext()));

        displayPolicy.addWindowLw(statusBar, attrs);
        displayPolicy.layoutWindowLw(statusBar, null, displayContent.mDisplayFrames);
        return statusBar;
    }

    /**
     * Returns an ActivityRecord instance with the specified attributes on the same task. By
     * constructing the ActivityRecord, forces {@link ActivityInfo} to be loaded with the compat
     * config settings.
     */
    private ActivityRecord buildActivityRecord(boolean supportsSizeChanges, int resizeMode,
            @ScreenOrientation int screenOrientation) {
        return new ActivityBuilder(mAtm)
                .setTask(mTask)
                .setResizeMode(resizeMode)
                .setSupportsSizeChanges(supportsSizeChanges)
                .setScreenOrientation(screenOrientation)
                .setComponent(ComponentName.createRelative(mContext,
                        SizeCompatTests.class.getName()))
                .setUid(android.os.Process.myUid())
                .build();
    }

    static void prepareUnresizable(ActivityRecord activity, int screenOrientation) {
        prepareUnresizable(activity, -1 /* maxAspect */, screenOrientation);
    }

    static void prepareUnresizable(ActivityRecord activity, float maxAspect,
            int screenOrientation) {
        prepareLimitedBounds(activity, maxAspect, screenOrientation, true /* isUnresizable */);
    }

    static void prepareLimitedBounds(ActivityRecord activity, int screenOrientation,
            boolean isUnresizable) {
        prepareLimitedBounds(activity, -1 /* maxAspect */, screenOrientation, isUnresizable);
    }

    /**
     * Setups {@link #mActivity} with restriction on its bounds, such as maxAspect, fixed
     * orientation, and/or whether it is resizable.
     */
    static void prepareLimitedBounds(ActivityRecord activity, float maxAspect,
            int screenOrientation, boolean isUnresizable) {
        activity.info.resizeMode = isUnresizable
                ? RESIZE_MODE_UNRESIZEABLE
                : RESIZE_MODE_RESIZEABLE;
        final Task task = activity.getTask();
        if (task != null) {
            // Update the Task resize value as activity will follow the task.
            task.mResizeMode = activity.info.resizeMode;
            task.getRootActivity().info.resizeMode = activity.info.resizeMode;
        }
        activity.mVisibleRequested = true;
        if (maxAspect >= 0) {
            activity.info.setMaxAspectRatio(maxAspect);
        }
        if (screenOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
            activity.info.screenOrientation = screenOrientation;
            activity.setRequestedOrientation(screenOrientation);
        }
        // Make sure to use the provided configuration to construct the size compat fields.
        activity.clearSizeCompatMode();
        activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
        // Make sure the display configuration reflects the change of activity.
        if (activity.mDisplayContent.updateOrientation()) {
            activity.mDisplayContent.sendNewConfiguration();
        }
    }

    /** Asserts that the size of activity is larger than its parent so it is scaling. */
    private void assertScaled() {
        assertTrue(mActivity.inSizeCompatMode());
        assertNotEquals(1f, mActivity.getSizeCompatScale(), 0.0001f /* delta */);
    }

    /** Asserts that the activity is best fitted in the parent. */
    private void assertFitted() {
        final boolean inSizeCompatMode = mActivity.inSizeCompatMode();
        final String failedConfigInfo = inSizeCompatMode
                ? ("ParentConfig=" + mActivity.getParent().getConfiguration()
                        + " ActivityConfig=" + mActivity.getConfiguration())
                : "";
        assertFalse(failedConfigInfo, inSizeCompatMode);
        assertFalse(mActivity.hasSizeCompatBounds());
    }

    /** Asserts the activity max bounds inherit from the TaskDisplayArea. */
    private void assertMaxBoundsInheritDisplayAreaBounds() {
        assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(mTask.getDisplayArea().getBounds());
    }

    /**
     * Asserts activity-level letterbox or size compat mode size compat mode, so activity max
     * bounds are sandboxed.
     */
    private void assertActivityMaxBoundsSandboxed() {
        assertActivityMaxBoundsSandboxed(mActivity);
    }

    /**
     * Asserts activity-level letterbox or size compat mode size compat mode on the specified
     * activity, so activity max bounds are sandboxed.
     */
    private void assertActivityMaxBoundsSandboxed(ActivityRecord activity) {
        // Activity max bounds are sandboxed due to size compat mode.
        assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
                .isEqualTo(activity.getWindowConfiguration().getBounds());
    }

    private void verifyLogAppCompatState(ActivityRecord activity, int state) {
        verify(mActivityMetricsLogger, atLeastOnce()).logAppCompatState(
                argThat(r -> activity == r && r.getAppCompatState() == state));
    }

    static Configuration rotateDisplay(DisplayContent display, int rotation) {
        final Configuration c = new Configuration();
        display.getDisplayRotation().setRotation(rotation);
        display.computeScreenConfiguration(c);
        display.onRequestedOverrideConfigurationChanged(c);
        return c;
    }

    private static void resizeDisplay(DisplayContent displayContent, int width, int height) {
        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity,
                displayContent.mBaseDisplayPhysicalXDpi, displayContent.mBaseDisplayPhysicalYDpi);
        final Configuration c = new Configuration();
        displayContent.computeScreenConfiguration(c);
        displayContent.onRequestedOverrideConfigurationChanged(c);
    }

    private static void setNeverConstrainDisplayApisFlag(@Nullable String value,
            boolean makeDefault) {
        DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
                CONFIG_NEVER_CONSTRAIN_DISPLAY_APIS, value, makeDefault);
    }

    private static void setNeverConstrainDisplayApisAllPackagesFlag(boolean value,
            boolean makeDefault) {
        DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
                CONFIG_NEVER_CONSTRAIN_DISPLAY_APIS_ALL_PACKAGES, String.valueOf(value),
                makeDefault);
    }

    private static void setAlwaysConstrainDisplayApisFlag(@Nullable String value,
            boolean makeDefault) {
        DeviceConfig.setProperty(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
                CONFIG_ALWAYS_CONSTRAIN_DISPLAY_APIS, value, makeDefault);
    }
}
