/*
 * Copyright (C) 2020 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.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.view.Surface.ROTATION_90;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.SizeCompatTests.prepareLimitedBounds;
import static com.android.server.wm.SizeCompatTests.prepareUnresizable;
import static com.android.server.wm.SizeCompatTests.rotateDisplay;

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

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.window.IDisplayAreaOrganizer;

import androidx.test.filters.SmallTest;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.List;

/**
 * Tests for the Dual DisplayAreaGroup device behavior.
 *
 * Build/Install/Run:
 *  atest WmTests:DualDisplayAreaGroupPolicyTest
 */
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
    private static final int FEATURE_FIRST_ROOT = FEATURE_VENDOR_FIRST;
    private static final int FEATURE_FIRST_TASK_CONTAINER = FEATURE_DEFAULT_TASK_CONTAINER;
    private static final int FEATURE_SECOND_ROOT = FEATURE_VENDOR_FIRST + 1;
    private static final int FEATURE_SECOND_TASK_CONTAINER = FEATURE_VENDOR_FIRST + 2;

    private DualDisplayContent mDisplay;
    private DisplayAreaGroup mFirstRoot;
    private DisplayAreaGroup mSecondRoot;
    private TaskDisplayArea mFirstTda;
    private TaskDisplayArea mSecondTda;
    private Task mFirstTask;
    private Task mSecondTask;
    private ActivityRecord mFirstActivity;
    private ActivityRecord mSecondActivity;

    @Before
    public void setUp() {
        // Let the Display to be created with the DualDisplay policy.
        final DisplayAreaPolicy.Provider policyProvider = new DualDisplayTestPolicyProvider();
        doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();

        // Display: 1920x1200 (landscape). First and second display are both 860x1200 (portrait).
        mDisplay = new DualDisplayContent.Builder(mAtm, 1920, 1200).build();
        mFirstRoot = mDisplay.mFirstRoot;
        mSecondRoot = mDisplay.mSecondRoot;
        mFirstTda = mDisplay.getTaskDisplayArea(FEATURE_FIRST_TASK_CONTAINER);
        mSecondTda = mDisplay.getTaskDisplayArea(FEATURE_SECOND_TASK_CONTAINER);
        mFirstTask = new TaskBuilder(mSupervisor)
                .setTaskDisplayArea(mFirstTda)
                .setCreateActivity(true)
                .build()
                .getBottomMostTask();
        mSecondTask = new TaskBuilder(mSupervisor)
                .setTaskDisplayArea(mSecondTda)
                .setCreateActivity(true)
                .build()
                .getBottomMostTask();
        mFirstActivity = mFirstTask.getTopNonFinishingActivity();
        mSecondActivity = mSecondTask.getTopNonFinishingActivity();

        spyOn(mDisplay);
        spyOn(mFirstRoot);
        spyOn(mSecondRoot);
    }

    @Test
    public void testNotIgnoreOrientationRequest_differentOrientationFromDisplay_reversesRequest() {
        mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LANDSCAPE);

        assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
        assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);

        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_PORTRAIT);

        assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
        assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
    }

    @Test
    public void testNotIgnoreOrientationRequest_onlyRespectsFocusedTaskDisplayArea() {
        mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        // Second TDA is not focused, so Display won't get the request
        prepareUnresizable(mSecondActivity, SCREEN_ORIENTATION_LANDSCAPE);

        assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_UNSPECIFIED);

        // First TDA is focused, so Display gets the request
        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LANDSCAPE);

        assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
    }

    @Test
    public void testIgnoreOrientationRequest_displayDoesNotReceiveOrientationChange() {
        mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LANDSCAPE);

        verify(mFirstRoot).onDescendantOrientationChanged(any());
        verify(mDisplay, never()).onDescendantOrientationChanged(any());
    }

    @Test
    public void testLaunchPortraitApp_fillsDisplayAreaGroup() {
        mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        prepareLimitedBounds(mFirstActivity, SCREEN_ORIENTATION_PORTRAIT,
                false /* isUnresizable */);
        final Rect dagBounds = new Rect(mFirstRoot.getBounds());
        final Rect taskBounds = new Rect(mFirstTask.getBounds());
        final Rect activityBounds = new Rect(mFirstActivity.getBounds());

        // DAG is portrait (860x1200), so Task and Activity fill DAG.
        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
        assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
        assertThat(taskBounds).isEqualTo(dagBounds);
        assertThat(activityBounds).isEqualTo(taskBounds);
    }

    @Test
    public void testLaunchPortraitApp_sizeCompatAfterRotation() {
        mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_PORTRAIT);
        final Rect dagBounds = new Rect(mFirstRoot.getBounds());
        final Rect activityBounds = new Rect(mFirstActivity.getBounds());

        rotateDisplay(mDisplay, ROTATION_90);
        final Rect newDagBounds = new Rect(mFirstRoot.getBounds());
        final Rect newTaskBounds = new Rect(mFirstTask.getBounds());
        final Rect activitySizeCompatBounds = new Rect(mFirstActivity.getBounds());
        final Rect activityConfigBounds =
                new Rect(mFirstActivity.getConfiguration().windowConfiguration.getBounds());

        // DAG is landscape (1200x860), no fixed orientation letterbox
        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
        assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
        assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
        assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
        assertThat(newTaskBounds).isEqualTo(newDagBounds);

        // Activity config bounds is unchanged, size compat bounds is (860x[860x860/1200=616])
        assertThat(mFirstActivity.getSizeCompatScale()).isLessThan(1f);
        assertThat(activityConfigBounds.width()).isEqualTo(activityBounds.width());
        assertThat(activityConfigBounds.height()).isEqualTo(activityBounds.height());
        assertThat(activitySizeCompatBounds.height()).isEqualTo(newTaskBounds.height());
        final float defaultAspectRatio = mFirstActivity.mWmService.mLetterboxConfiguration
                .getDefaultMinAspectRatioForUnresizableApps();
        assertEquals(activitySizeCompatBounds.width(),
                newTaskBounds.height() / defaultAspectRatio, 0.5);
    }

    @Test
    public void testLaunchLandscapeApp_activityIsLetterboxForFixedOrientationInDisplayAreaGroup() {
        mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LANDSCAPE);
        final Rect dagBounds = new Rect(mFirstRoot.getBounds());
        final Rect taskBounds = new Rect(mFirstTask.getBounds());
        final Rect activityBounds = new Rect(mFirstActivity.getBounds());

        // DAG is portrait (860x1200), and activity is letterboxed for fixed orientation
        // (860x[860x860/1200=616]). Task fills DAG.
        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
        assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
        assertThat(taskBounds).isEqualTo(dagBounds);
        assertThat(activityBounds.width()).isEqualTo(dagBounds.width());
        final float defaultAspectRatio = mFirstActivity.mWmService.mLetterboxConfiguration
                .getDefaultMinAspectRatioForUnresizableApps();
        assertEquals(activityBounds.height(), dagBounds.width() / defaultAspectRatio, 0.5);
    }

    @Test
    public void testLaunchLandscapeApp_fixedOrientationLetterboxBecomesSizeCompatAfterRotation() {
        mFirstRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);

        prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LANDSCAPE);
        final Rect dagBounds = new Rect(mFirstRoot.getBounds());
        final Rect activityBounds = new Rect(mFirstActivity.getBounds());

        rotateDisplay(mDisplay, ROTATION_90);
        final Rect newDagBounds = new Rect(mFirstRoot.getBounds());
        final Rect newTaskBounds = new Rect(mFirstTask.getBounds());
        final Rect newActivityBounds = new Rect(mFirstActivity.getBounds());

        // DAG is landscape (1200x860), no fixed orientation letterbox
        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
        assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
        assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
        assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
        assertThat(newTaskBounds).isEqualTo(newDagBounds);

        // Because we don't scale up, there is no size compat bounds and app bounds is the same as
        // the previous bounds.
        assertThat(mFirstActivity.hasSizeCompatBounds()).isFalse();
        assertThat(newActivityBounds.width()).isEqualTo(activityBounds.width());
        assertThat(newActivityBounds.height()).isEqualTo(activityBounds.height());
    }

    @Test
    public void testPlaceImeContainer_reparentToTargetDisplayAreaGroup() {
        setupImeWindow();
        final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer();
        final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD);

        // By default, the ime container is attached to DC as defined in DAPolicy.
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
        assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);

        final WindowState firstActivityWin =
                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
                        "firstActivityWin");
        spyOn(firstActivityWin);
        final WindowState secondActivityWin =
                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mSecondActivity,
                        "firstActivityWin");
        spyOn(secondActivityWin);

        // firstActivityWin should be the target
        doReturn(true).when(firstActivityWin).canBeImeTarget();
        doReturn(false).when(secondActivityWin).canBeImeTarget();

        WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);

        assertThat(imeTarget).isEqualTo(firstActivityWin);
        verify(mFirstRoot).placeImeContainer(imeContainer);
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mFirstRoot);
        assertThat(imeContainer.getParent().asDisplayArea().mFeatureId)
                .isEqualTo(FEATURE_IME_PLACEHOLDER);
        assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isNull();
        assertThat(mFirstRoot.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);
        assertThat(mSecondRoot.findAreaForTokenInLayer(imeToken)).isNull();

        // secondActivityWin should be the target
        doReturn(false).when(firstActivityWin).canBeImeTarget();
        doReturn(true).when(secondActivityWin).canBeImeTarget();

        imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);

        assertThat(imeTarget).isEqualTo(secondActivityWin);
        verify(mSecondRoot).placeImeContainer(imeContainer);
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mSecondRoot);
        assertThat(imeContainer.getParent().asDisplayArea().mFeatureId)
                .isEqualTo(FEATURE_IME_PLACEHOLDER);
        assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isNull();
        assertThat(mFirstRoot.findAreaForTokenInLayer(imeToken)).isNull();
        assertThat(mSecondRoot.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);
    }

    @Test
    public void testPlaceImeContainer_hidesImeWhenParentChanges() {
        setupImeWindow();
        final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer();
        final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD);
        final WindowState firstActivityWin =
                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
                        "firstActivityWin");
        spyOn(firstActivityWin);
        final WindowState secondActivityWin =
                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mSecondActivity,
                        "secondActivityWin");
        spyOn(secondActivityWin);

        // firstActivityWin should be the target
        doReturn(true).when(firstActivityWin).canBeImeTarget();
        doReturn(false).when(secondActivityWin).canBeImeTarget();

        WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);
        assertThat(imeTarget).isEqualTo(firstActivityWin);
        verify(mFirstRoot).placeImeContainer(imeContainer);

        // secondActivityWin should be the target
        doReturn(false).when(firstActivityWin).canBeImeTarget();
        doReturn(true).when(secondActivityWin).canBeImeTarget();

        spyOn(mDisplay.mInputMethodWindow);
        imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);

        assertThat(imeTarget).isEqualTo(secondActivityWin);
        verify(mSecondRoot).placeImeContainer(imeContainer);
        // verify hide() was called on InputMethodWindow.
        verify(mDisplay.mInputMethodWindow).hide(false /* doAnimation */, false /* requestAnim */);
    }

    @Test
    public void testPlaceImeContainer_skipReparentForOrganizedImeContainer() {
        setupImeWindow();
        final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer();
        final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD);

        // By default, the ime container is attached to DC as defined in DAPolicy.
        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
        assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);

        final WindowState firstActivityWin =
                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
                        "firstActivityWin");
        spyOn(firstActivityWin);
        // firstActivityWin should be the target
        doReturn(true).when(firstActivityWin).canBeImeTarget();

        // Main precondition for this test: organize the ImeContainer.
        final IDisplayAreaOrganizer mockImeOrganizer = mock(IDisplayAreaOrganizer.class);
        when(mockImeOrganizer.asBinder()).thenReturn(new Binder());
        imeContainer.setOrganizer(mockImeOrganizer);

        WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);

        // The IME target must be updated but the don't reparent organized ImeContainers.
        // See DisplayAreaOrganizer#FEATURE_IME.
        assertThat(imeTarget).isEqualTo(firstActivityWin);
        verify(mFirstRoot, never()).placeImeContainer(imeContainer);

        // Clean up organizer.
        imeContainer.setOrganizer(null);
    }

    @Test
    public void testResizableFixedOrientationApp_fixedOrientationLetterboxing() {
        mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
        mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);

        // Launch portrait on first DAG
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
        prepareLimitedBounds(mFirstActivity, SCREEN_ORIENTATION_PORTRAIT,
                false /* isUnresizable */);

        // Display in landscape (as opposite to DAG), first DAG and activity in portrait
        assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
        assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
        assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
        assertThat(mFirstActivity.inSizeCompatMode()).isFalse();

        // Launch portrait on second DAG
        mDisplay.onLastFocusedTaskDisplayAreaChanged(mSecondTda);
        prepareLimitedBounds(mSecondActivity, SCREEN_ORIENTATION_LANDSCAPE,
                false /* isUnresizable */);

        // Display in portrait (as opposite to DAG), first DAG and activity in landscape
        assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
        assertThat(mSecondRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
        assertThat(mSecondActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
        assertThat(mSecondActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
        assertThat(mSecondActivity.inSizeCompatMode()).isFalse();

        // First activity is letterboxed in portrait as requested.
        assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
        assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
        assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
        assertThat(mFirstActivity.inSizeCompatMode()).isFalse();

    }

    private void setupImeWindow() {
        final WindowState imeWindow = createWindow(null /* parent */,
                TYPE_INPUT_METHOD, mDisplay, "mImeWindow");
        imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
        mDisplay.mInputMethodWindow = imeWindow;
    }

    private WindowToken tokenOfType(int type) {
        return new WindowToken.Builder(mWm, new Binder(), type)
                .setDisplayContent(mDisplay).build();
    }

    /** Display with two {@link DisplayAreaGroup}. Each of them take half of the screen. */
    static class DualDisplayContent extends TestDisplayContent {
        final DisplayAreaGroup mFirstRoot;
        final DisplayAreaGroup mSecondRoot;
        final Rect mLastDisplayBounds;

        /** Please use the {@link Builder} to create. */
        DualDisplayContent(RootWindowContainer rootWindowContainer,
                Display display) {
            super(rootWindowContainer, display);

            mFirstRoot = getGroupRoot(FEATURE_FIRST_ROOT);
            mSecondRoot = getGroupRoot(FEATURE_SECOND_ROOT);
            mLastDisplayBounds = new Rect(getBounds());
            updateDisplayAreaGroupBounds();
        }

        DisplayAreaGroup getGroupRoot(int rootFeatureId) {
            DisplayArea da = getDisplayArea(rootFeatureId);
            assertThat(da).isInstanceOf(DisplayAreaGroup.class);
            return (DisplayAreaGroup) da;
        }

        TaskDisplayArea getTaskDisplayArea(int tdaFeatureId) {
            DisplayArea da = getDisplayArea(tdaFeatureId);
            assertThat(da).isInstanceOf(TaskDisplayArea.class);
            return (TaskDisplayArea) da;
        }

        DisplayArea getDisplayArea(int featureId) {
            final DisplayArea displayArea =
                    getItemFromDisplayAreas(da -> da.mFeatureId == featureId ? da : null);
            assertThat(displayArea).isNotNull();
            return displayArea;
        }

        @Override
        public void onConfigurationChanged(Configuration newParentConfig) {
            super.onConfigurationChanged(newParentConfig);

            final Rect curBounds = getBounds();
            if (mLastDisplayBounds != null && !mLastDisplayBounds.equals(curBounds)) {
                mLastDisplayBounds.set(curBounds);
                updateDisplayAreaGroupBounds();
            }
        }

        /** Updates first and second {@link DisplayAreaGroup} to take half of the screen. */
        private void updateDisplayAreaGroupBounds() {
            if (mFirstRoot == null || mSecondRoot == null) {
                return;
            }

            final Rect bounds = mLastDisplayBounds;
            Rect groupBounds1, groupBounds2;
            if (bounds.width() >= bounds.height()) {
                groupBounds1 = new Rect(bounds.left, bounds.top,
                        (bounds.right + bounds.left) / 2, bounds.bottom);

                groupBounds2 = new Rect((bounds.right + bounds.left) / 2, bounds.top,
                        bounds.right, bounds.bottom);
            } else {
                groupBounds1 = new Rect(bounds.left, bounds.top,
                        bounds.right, (bounds.top + bounds.bottom) / 2);

                groupBounds2 = new Rect(bounds.left,
                        (bounds.top + bounds.bottom) / 2, bounds.right, bounds.bottom);
            }
            mFirstRoot.setBounds(groupBounds1);
            mSecondRoot.setBounds(groupBounds2);
        }

        static class Builder extends TestDisplayContent.Builder {

            Builder(ActivityTaskManagerService service, int width, int height) {
                super(service, width, height);
            }

            @Override
            TestDisplayContent createInternal(Display display) {
                return new DualDisplayContent(mService.mRootWindowContainer, display);
            }

            DualDisplayContent build() {
                return (DualDisplayContent) super.build();
            }
        }
    }

    /** Policy to create a dual {@link DisplayAreaGroup} policy in test. */
    static class DualDisplayTestPolicyProvider implements DisplayAreaPolicy.Provider {

        @Override
        public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content,
                RootDisplayArea root, DisplayArea.Tokens imeContainer) {
            // Root
            // Include FEATURE_WINDOWED_MAGNIFICATION because it will be used as the screen rotation
            // layer
            DisplayAreaPolicyBuilder.HierarchyBuilder rootHierarchy =
                    new DisplayAreaPolicyBuilder.HierarchyBuilder(root)
                            .setImeContainer(imeContainer)
                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
                                    wmService.mPolicy,
                                    "WindowedMagnification", FEATURE_WINDOWED_MAGNIFICATION)
                                    .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                                    .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                                    .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
                                    .build())
                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
                                    wmService.mPolicy,
                                    "ImePlaceholder", FEATURE_IME_PLACEHOLDER)
                                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
                                    .build());

            // First
            final RootDisplayArea firstRoot = new DisplayAreaGroup(wmService, "FirstRoot",
                    FEATURE_FIRST_ROOT);
            final TaskDisplayArea firstTaskDisplayArea = new TaskDisplayArea(content, wmService,
                    "FirstTaskDisplayArea", FEATURE_FIRST_TASK_CONTAINER);
            final List<TaskDisplayArea> firstTdaList = new ArrayList<>();
            firstTdaList.add(firstTaskDisplayArea);
            DisplayAreaPolicyBuilder.HierarchyBuilder firstHierarchy =
                    new DisplayAreaPolicyBuilder.HierarchyBuilder(firstRoot)
                            .setTaskDisplayAreas(firstTdaList)
                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
                                    wmService.mPolicy,
                                    "ImePlaceholder", FEATURE_IME_PLACEHOLDER)
                                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
                                    .build());

            // Second
            final RootDisplayArea secondRoot = new DisplayAreaGroup(wmService, "SecondRoot",
                    FEATURE_SECOND_ROOT);
            final TaskDisplayArea secondTaskDisplayArea = new TaskDisplayArea(content, wmService,
                    "SecondTaskDisplayArea", FEATURE_SECOND_TASK_CONTAINER);
            final List<TaskDisplayArea> secondTdaList = new ArrayList<>();
            secondTdaList.add(secondTaskDisplayArea);
            DisplayAreaPolicyBuilder.HierarchyBuilder secondHierarchy =
                    new DisplayAreaPolicyBuilder.HierarchyBuilder(secondRoot)
                            .setTaskDisplayAreas(secondTdaList)
                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
                                    wmService.mPolicy,
                                    "ImePlaceholder", FEATURE_IME_PLACEHOLDER)
                                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
                                    .build());

            return new DisplayAreaPolicyBuilder()
                    .setRootHierarchy(rootHierarchy)
                    .addDisplayAreaGroupHierarchy(firstHierarchy)
                    .addDisplayAreaGroupHierarchy(secondHierarchy)
                    .build(wmService);
        }
    }
}
