/*
 * Copyright (C) 2018 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.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
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_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
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.os.Process.NOBODY_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
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.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REQUESTED;
import static com.android.server.wm.ActivityRecord.State.DESTROYED;
import static com.android.server.wm.ActivityRecord.State.DESTROYING;
import static com.android.server.wm.ActivityRecord.State.FINISHING;
import static com.android.server.wm.ActivityRecord.State.INITIALIZING;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STARTED;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_INVISIBLE;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.ROOT_TASK_CLIP_NONE;

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.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;

import android.app.ActivityOptions;
import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.DestroyActivityItem;
import android.app.servertransaction.PauseActivityItem;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
import android.view.DisplayInfo;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner.Stub;
import android.view.IWindowManager;
import android.view.IWindowSession;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.InsetsVisibilities;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.window.TaskSnapshot;

import androidx.test.filters.MediumTest;

import com.android.internal.R;
import com.android.server.wm.ActivityRecord.State;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;

import java.util.ArrayList;
import java.util.function.BiConsumer;
import java.util.function.Consumer;


/**
 * Tests for the {@link ActivityRecord} class.
 *
 * Build/Install/Run:
 *  atest WmTests:ActivityRecordTests
 */
@MediumTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class ActivityRecordTests extends WindowTestsBase {

    private final String mPackageName = getInstrumentation().getTargetContext().getPackageName();

    @Before
    public void setUp() throws Exception {
        setBooted(mAtm);
        // Because the booted state is set, avoid starting real home if there is no task.
        doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
    }

    private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
        return new TestStartingWindowOrganizer(mAtm,
                mSystemServicesTestRule.getPowerManagerWrapper());
    }

    @Test
    public void testTaskFragmentCleanupOnClearingTask() {
        final ActivityRecord activity = createActivityWith2LevelTask();
        final Task task = activity.getTask();
        final TaskFragment taskFragment = activity.getTaskFragment();
        activity.onParentChanged(null /*newParent*/, task);
        verify(taskFragment).cleanUpActivityReferences(any());
    }

    @Test
    public void testTaskFragmentCleanupOnActivityRemoval() {
        final ActivityRecord activity = createActivityWith2LevelTask();
        final Task task = activity.getTask();
        final TaskFragment taskFragment = activity.getTaskFragment();
        task.removeChild(activity);
        verify(taskFragment).cleanUpActivityReferences(any());
    }

    @Test
    public void testRootTaskCleanupOnTaskRemoval() {
        final ActivityRecord activity = createActivityWith2LevelTask();
        final Task task = activity.getTask();
        final Task rootTask = activity.getRootTask();
        rootTask.removeChild(task, null /*reason*/);
        // parentTask should be gone on task removal.
        assertNull(mAtm.mRootWindowContainer.getRootTask(rootTask.mTaskId));
    }

    @Test
    public void testRemoveChildWithOverlayActivity() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        final ActivityRecord overlayActivity = new ActivityBuilder(mAtm).setTask(task).build();
        overlayActivity.setTaskOverlay(true);
        final ActivityRecord overlayActivity2 = new ActivityBuilder(mAtm).setTask(task).build();
        overlayActivity2.setTaskOverlay(true);

        task.removeChild(overlayActivity2, "test");
        verify(mSupervisor, never()).removeTask(any(), anyBoolean(), anyBoolean(), any());
    }

    @Test
    public void testNoCleanupMovingActivityInSameStack() {
        final ActivityRecord activity = createActivityWith2LevelTask();
        final Task rootTask = activity.getRootTask();
        final Task newTask = createTaskInRootTask(rootTask, 0 /* userId */);
        activity.reparent(newTask, 0, null /*reason*/);
        verify(rootTask, times(0)).cleanUpActivityReferences(any());
    }

    @Test
    public void testPausingWhenVisibleFromStopped() throws Exception {
        final ActivityRecord activity = createActivityWithTask();
        final MutableBoolean pauseFound = new MutableBoolean(false);
        doAnswer((InvocationOnMock invocationOnMock) -> {
            final ClientTransaction transaction = invocationOnMock.getArgument(0);
            if (transaction.getLifecycleStateRequest() instanceof PauseActivityItem) {
                pauseFound.value = true;
            }
            return null;
        }).when(activity.app.getThread()).scheduleTransaction(any());

        activity.setState(STOPPED, "testPausingWhenVisibleFromStopped");

        // The activity is in the focused stack so it should be resumed.
        activity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
        assertTrue(activity.isState(RESUMED));
        assertFalse(pauseFound.value);

        // Make the activity non focusable
        activity.setState(STOPPED, "testPausingWhenVisibleFromStopped");
        doReturn(false).when(activity).isFocusable();

        // If the activity is not focusable, it should move to paused.
        activity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
        assertTrue(activity.isState(PAUSING));
        assertTrue(pauseFound.value);

        // Make sure that the state does not change for current non-stopping states.
        activity.setState(INITIALIZING, "testPausingWhenVisibleFromStopped");
        doReturn(true).when(activity).isFocusable();

        activity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);

        assertTrue(activity.isState(INITIALIZING));

        // Make sure the state does not change if we are not the current top activity.
        activity.setState(STOPPED, "testPausingWhenVisibleFromStopped behind");

        final Task task = activity.getTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
        task.mTranslucentActivityWaiting = topActivity;
        activity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
        assertTrue(activity.isState(STARTED));

        task.mTranslucentActivityWaiting = null;
        topActivity.setOccludesParent(false);
        activity.setState(STOPPED, "testPausingWhenVisibleFromStopped behind non-opaque");
        activity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
        assertTrue(activity.isState(STARTED));
    }

    private void ensureActivityConfiguration(ActivityRecord activity) {
        activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
    }

    @Test
    public void testCanBeLaunchedOnDisplay() {
        mAtm.mSupportsMultiWindow = true;
        final ActivityRecord activity = new ActivityBuilder(mAtm).build();

        // An activity can be launched on default display.
        assertTrue(activity.canBeLaunchedOnDisplay(DEFAULT_DISPLAY));
        // An activity cannot be launched on a non-existent display.
        assertFalse(activity.canBeLaunchedOnDisplay(Integer.MAX_VALUE));
    }

    @Test
    public void testsApplyOptionsLocked() {
        final ActivityRecord activity = createActivityWithTask();
        ActivityOptions activityOptions = ActivityOptions.makeBasic();

        // Set and apply options for ActivityRecord. Pending options should be cleared
        activity.updateOptionsLocked(activityOptions);
        activity.applyOptionsAnimation();
        assertNull(activity.getOptions());

        // Set options for two ActivityRecords in same Task. Apply one ActivityRecord options.
        // Pending options should be cleared for both ActivityRecords
        ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(activity.getTask()).build();
        activity2.updateOptionsLocked(activityOptions);
        activity.updateOptionsLocked(activityOptions);
        activity.applyOptionsAnimation();
        assertNull(activity.getOptions());
        assertNull(activity2.getOptions());

        // Set options for two ActivityRecords in separate Tasks. Apply one ActivityRecord options.
        // Pending options should be cleared for only ActivityRecord that was applied
        activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
        activity2.updateOptionsLocked(activityOptions);
        activity.updateOptionsLocked(activityOptions);
        activity.applyOptionsAnimation();
        assertNull(activity.getOptions());
        assertNotNull(activity2.getOptions());
    }

    @Test
    public void testNewOverrideConfigurationIncrementsSeq() {
        final ActivityRecord activity = createActivityWithTask();
        final Configuration newConfig = new Configuration();

        final int prevSeq = activity.getMergedOverrideConfiguration().seq;
        activity.onRequestedOverrideConfigurationChanged(newConfig);
        assertEquals(prevSeq + 1, activity.getMergedOverrideConfiguration().seq);
    }

    @Test
    public void testNewParentConfigurationIncrementsSeq() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        final Configuration newConfig = new Configuration(
                task.getRequestedOverrideConfiguration());
        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
                ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;

        final int prevSeq = activity.getMergedOverrideConfiguration().seq;
        task.onRequestedOverrideConfigurationChanged(newConfig);
        assertEquals(prevSeq + 1, activity.getMergedOverrideConfiguration().seq);
    }

    @Test
    public void testSetsRelaunchReason_NotDragResizing() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        activity.setState(RESUMED, "Testing");

        task.onRequestedOverrideConfigurationChanged(task.getConfiguration());
        activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                activity.getConfiguration()));

        activity.info.configChanges &= ~CONFIG_ORIENTATION;
        final Configuration newConfig = new Configuration(task.getConfiguration());
        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
                ? ORIENTATION_LANDSCAPE
                : ORIENTATION_PORTRAIT;
        task.onRequestedOverrideConfigurationChanged(newConfig);

        activity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;

        ensureActivityConfiguration(activity);

        assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE,
                activity.mRelaunchReason);
    }

    @Test
    public void testSetsRelaunchReason_DragResizing() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        activity.setState(RESUMED, "Testing");

        task.onRequestedOverrideConfigurationChanged(task.getConfiguration());
        activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                activity.getConfiguration()));

        activity.info.configChanges &= ~CONFIG_ORIENTATION;
        final Configuration newConfig = new Configuration(task.getConfiguration());
        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
                ? ORIENTATION_LANDSCAPE
                : ORIENTATION_PORTRAIT;
        task.onRequestedOverrideConfigurationChanged(newConfig);

        doReturn(true).when(task).isDragResizing();

        activity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;

        ensureActivityConfiguration(activity);

        assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE,
                activity.mRelaunchReason);
    }

    @Test
    public void testRelaunchClearTopWaitingTranslucent() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        activity.setState(RESUMED, "Testing");

        task.onRequestedOverrideConfigurationChanged(task.getConfiguration());
        activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                activity.getConfiguration()));

        activity.info.configChanges &= ~CONFIG_ORIENTATION;
        final Configuration newConfig = new Configuration(task.getConfiguration());
        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
                ? ORIENTATION_LANDSCAPE
                : ORIENTATION_PORTRAIT;
        task.onRequestedOverrideConfigurationChanged(newConfig);
        task.mTranslucentActivityWaiting = activity;
        ensureActivityConfiguration(activity);
        assertNull(task.mTranslucentActivityWaiting);
    }

    @Test
    public void testSetsRelaunchReason_NonResizeConfigChanges() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        activity.setState(RESUMED, "Testing");

        task.onRequestedOverrideConfigurationChanged(task.getConfiguration());
        activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                activity.getConfiguration()));

        activity.info.configChanges &= ~ActivityInfo.CONFIG_FONT_SCALE;
        final Configuration newConfig = new Configuration(task.getConfiguration());
        newConfig.fontScale = 5;
        task.onRequestedOverrideConfigurationChanged(newConfig);

        activity.mRelaunchReason =
                ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;

        ensureActivityConfiguration(activity);

        assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_NONE,
                activity.mRelaunchReason);
    }

    @Test
    public void testDestroyedActivityNotScheduleConfigChanged() throws RemoteException {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setConfigChanges(CONFIG_ORIENTATION)
                .build();
        final Task task = activity.getTask();
        activity.setState(DESTROYED, "Testing");
        clearInvocations(mAtm.getLifecycleManager());

        final Configuration newConfig = new Configuration(task.getConfiguration());
        newConfig.orientation = newConfig.orientation == ORIENTATION_PORTRAIT
                ? ORIENTATION_LANDSCAPE
                : ORIENTATION_PORTRAIT;
        task.onRequestedOverrideConfigurationChanged(newConfig);

        ensureActivityConfiguration(activity);

        verify(mAtm.getLifecycleManager(), never())
                .scheduleTransaction(any(), any(), isA(ActivityConfigurationChangeItem.class));
    }

    @Test
    public void testSetRequestedOrientationUpdatesConfiguration() throws Exception {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setConfigChanges(CONFIG_ORIENTATION | CONFIG_SCREEN_LAYOUT)
                .build();
        activity.setState(RESUMED, "Testing");

        activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                activity.getConfiguration()));

        clearInvocations(mAtm.getLifecycleManager());
        final Configuration newConfig = new Configuration(activity.getConfiguration());
        final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
        final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
        if (newConfig.orientation == ORIENTATION_PORTRAIT) {
            newConfig.orientation = ORIENTATION_LANDSCAPE;
            newConfig.screenWidthDp = longSide;
            newConfig.screenHeightDp = shortSide;
        } else {
            newConfig.orientation = ORIENTATION_PORTRAIT;
            newConfig.screenWidthDp = shortSide;
            newConfig.screenHeightDp = longSide;
        }

        // Mimic the behavior that display doesn't handle app's requested orientation.
        final DisplayContent dc = activity.getTask().getDisplayContent();
        doReturn(false).when(dc).onDescendantOrientationChanged(any());
        doReturn(false).when(dc).handlesOrientationChangeFromDescendant();

        final int requestedOrientation;
        switch (newConfig.orientation) {
            case ORIENTATION_LANDSCAPE:
                requestedOrientation = SCREEN_ORIENTATION_LANDSCAPE;
                break;
            case ORIENTATION_PORTRAIT:
                requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
            default:
                throw new IllegalStateException("Orientation in new config should be either"
                        + "landscape or portrait.");
        }
        activity.setRequestedOrientation(requestedOrientation);

        final ActivityConfigurationChangeItem expected =
                ActivityConfigurationChangeItem.obtain(newConfig);
        verify(mAtm.getLifecycleManager()).scheduleTransaction(eq(activity.app.getThread()),
                eq(activity.appToken), eq(expected));
    }

    @Test
    public void ignoreRequestedOrientationInFreeformWindows() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        task.setWindowingMode(WINDOWING_MODE_FREEFORM);
        final Rect stableRect = new Rect();
        task.mDisplayContent.getStableRect(stableRect);

        // Carve out non-decor insets from stableRect
        final Rect insets = new Rect();
        final DisplayInfo displayInfo = task.mDisplayContent.getDisplayInfo();
        final DisplayPolicy policy = task.mDisplayContent.getDisplayPolicy();
        policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
                displayInfo.logicalHeight, displayInfo.displayCutout, insets);
        policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation);
        Task.intersectWithInsetsIfFits(stableRect, stableRect, insets);

        final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
        final Rect bounds = new Rect(stableRect);
        if (isScreenPortrait) {
            // Landscape bounds
            final int newHeight = stableRect.width() - 10;
            bounds.top = stableRect.top + (stableRect.height() - newHeight) / 2;
            bounds.bottom = bounds.top + newHeight;
        } else {
            // Portrait bounds
            final int newWidth = stableRect.height() - 10;
            bounds.left = stableRect.left + (stableRect.width() - newWidth) / 2;
            bounds.right = bounds.left + newWidth;
        }
        task.setBounds(bounds);

        // Requests orientation that's different from its bounds.
        activity.setRequestedOrientation(
                isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);

        // Asserts it has orientation derived from bounds.
        assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
                activity.getConfiguration().orientation);
    }

    @Test
    public void ignoreRequestedOrientationForResizableInSplitWindows() {
        final ActivityRecord activity = createActivityWith2LevelTask();
        final Task task = activity.getTask();
        final Task rootTask = activity.getRootTask();
        rootTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final Rect stableRect = new Rect();
        rootTask.mDisplayContent.getStableRect(stableRect);

        // Carve out non-decor insets from stableRect
        final Rect insets = new Rect();
        final DisplayInfo displayInfo = rootTask.mDisplayContent.getDisplayInfo();
        final DisplayPolicy policy = rootTask.mDisplayContent.getDisplayPolicy();
        policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
                displayInfo.logicalHeight, displayInfo.displayCutout, insets);
        policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation);
        Task.intersectWithInsetsIfFits(stableRect, stableRect, insets);

        final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
        final Rect bounds = new Rect(stableRect);
        if (isScreenPortrait) {
            // Landscape bounds
            final int newHeight = stableRect.width() - 10;
            bounds.top = stableRect.top + (stableRect.height() - newHeight) / 2;
            bounds.bottom = bounds.top + newHeight;
        } else {
            // Portrait bounds
            final int newWidth = stableRect.height() - 10;
            bounds.left = stableRect.left + (stableRect.width() - newWidth) / 2;
            bounds.right = bounds.left + newWidth;
        }
        task.setBounds(bounds);

        final int activityCurOrientation = activity.getConfiguration().orientation;

        // Requests orientation that's different from its bounds.
        activity.setRequestedOrientation(activityCurOrientation == ORIENTATION_LANDSCAPE
                ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);

        // Asserts fixed orientation request is ignored, and the orientation is not changed
        // (fill Task).
        assertEquals(activityCurOrientation, activity.getConfiguration().orientation);
        assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void respectRequestedOrientationForNonResizableInSplitWindows() {
        final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea();
        spyOn(tda);
        doReturn(true).when(tda).supportsNonResizableMultiWindow();
        final Task rootTask = mDisplayContent.getDefaultTaskDisplayArea().createRootTask(
                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
        rootTask.setBounds(0, 0, 1000, 500);
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setParentTask(rootTask)
                .setCreateTask(true)
                .setOnTop(true)
                .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
                .build();
        final Task task = activity.getTask();

        // Task in landscape.
        assertEquals(ORIENTATION_LANDSCAPE, task.getConfiguration().orientation);

        // Asserts fixed orientation request is respected, and the orientation is not changed.
        assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);

        // Clear size compat.
        activity.clearSizeCompatMode();
        activity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
        mDisplayContent.sendNewConfiguration();

        // Relaunching the app should still respect the orientation request.
        assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);
        assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void testShouldMakeActive_deferredResume() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(STOPPED, "Testing");

        mSupervisor.beginDeferResume();
        assertEquals(false, activity.shouldMakeActive(null /* activeActivity */));

        mSupervisor.endDeferResume();
        assertEquals(true, activity.shouldMakeActive(null /* activeActivity */));
    }

    @Test
    public void testShouldMakeActive_nonTopVisible() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        ActivityRecord finishingActivity = new ActivityBuilder(mAtm).setTask(task).build();
        finishingActivity.finishing = true;
        ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
        activity.setState(STOPPED, "Testing");

        assertEquals(false, activity.shouldMakeActive(null /* activeActivity */));
    }

    @Test
    public void testShouldResume_stackVisibility() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        activity.setState(STOPPED, "Testing");

        doReturn(TASK_FRAGMENT_VISIBILITY_VISIBLE).when(task).getVisibility(null);
        assertEquals(true, activity.shouldResumeActivity(null /* activeActivity */));

        doReturn(TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT)
                .when(task).getVisibility(null);
        assertEquals(false, activity.shouldResumeActivity(null /* activeActivity */));

        doReturn(TASK_FRAGMENT_VISIBILITY_INVISIBLE).when(task).getVisibility(null);
        assertEquals(false, activity.shouldResumeActivity(null /* activeActivity */));
    }

    @Test
    public void testShouldResumeOrPauseWithResults() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        activity.setState(STOPPED, "Testing");

        ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
        activity.addResultLocked(topActivity, "resultWho", 0, 0, new Intent());
        topActivity.finishing = true;

        doReturn(TASK_FRAGMENT_VISIBILITY_VISIBLE).when(task).getVisibility(null);
        assertEquals(true, activity.shouldResumeActivity(null /* activeActivity */));
        assertEquals(false, activity.shouldPauseActivity(null /*activeActivity */));
    }

    @Test
    public void testPushConfigurationWhenLaunchTaskBehind() throws Exception {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setLaunchTaskBehind(true)
                .setConfigChanges(CONFIG_ORIENTATION | CONFIG_SCREEN_LAYOUT)
                .build();
        final Task task = activity.getTask();
        activity.setState(STOPPED, "Testing");

        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        try {
            clearInvocations(mAtm.getLifecycleManager());
            doReturn(false).when(stack).isTranslucent(any());
            assertTrue(task.shouldBeVisible(null /* starting */));

            activity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
                    activity.getConfiguration()));

            final Configuration newConfig = new Configuration(activity.getConfiguration());
            final int shortSide = Math.min(newConfig.screenWidthDp, newConfig.screenHeightDp);
            final int longSide = Math.max(newConfig.screenWidthDp, newConfig.screenHeightDp);
            if (newConfig.orientation == ORIENTATION_PORTRAIT) {
                newConfig.orientation = ORIENTATION_LANDSCAPE;
                newConfig.screenWidthDp = longSide;
                newConfig.screenHeightDp = shortSide;
            } else {
                newConfig.orientation = ORIENTATION_PORTRAIT;
                newConfig.screenWidthDp = shortSide;
                newConfig.screenHeightDp = longSide;
            }

            task.onConfigurationChanged(newConfig);

            activity.ensureActivityConfiguration(0 /* globalChanges */,
                    false /* preserveWindow */, true /* ignoreStopState */);

            final ActivityConfigurationChangeItem expected =
                    ActivityConfigurationChangeItem.obtain(newConfig);
            verify(mAtm.getLifecycleManager()).scheduleTransaction(
                    eq(activity.app.getThread()), eq(activity.appToken), eq(expected));
        } finally {
            stack.getDisplayArea().removeChild(stack);
        }
    }

    @Test
    public void testShouldStartWhenMakeClientActive() {
        final ActivityRecord activity = createActivityWithTask();
        ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(activity.getTask()).build();
        topActivity.setOccludesParent(false);
        activity.setState(STOPPED, "Testing");
        activity.setVisibility(true);
        activity.makeActiveIfNeeded(null /* activeActivity */);
        assertEquals(STARTED, activity.getState());
    }

    @Test
    public void testTakeOptions() {
        final ActivityRecord activity = createActivityWithTask();
        ActivityOptions opts = ActivityOptions.makeRemoteAnimation(
                new RemoteAnimationAdapter(new Stub() {

                    @Override
                    public void onAnimationStart(@WindowManager.TransitionOldType int transit,
                            RemoteAnimationTarget[] apps,
                            RemoteAnimationTarget[] wallpapers,
                            RemoteAnimationTarget[] nonApps,
                            IRemoteAnimationFinishedCallback finishedCallback) {
                    }

                    @Override
                    public void onAnimationCancelled() {
                    }
                }, 0, 0));
        activity.updateOptionsLocked(opts);
        assertNotNull(activity.takeOptions());
        assertNull(activity.getOptions());

        final AppTransition appTransition = activity.mDisplayContent.mAppTransition;
        spyOn(appTransition);
        activity.applyOptionsAnimation();

        verify(appTransition).overridePendingAppTransitionRemote(any());
    }

    @Test
    public void testCanLaunchHomeActivityFromChooser() {
        ComponentName chooserComponent = ComponentName.unflattenFromString(
                Resources.getSystem().getString(R.string.config_chooserActivity));
        ActivityRecord chooserActivity = new ActivityBuilder(mAtm).setComponent(
                chooserComponent).build();
        assertThat(chooserActivity.canLaunchHomeActivity(NOBODY_UID, chooserActivity)).isTrue();
    }

    /**
     * Verify that an {@link ActivityRecord} reports that it has saved state after creation, and
     * that it is cleared after activity is resumed.
     */
    @Test
    public void testHasSavedState() {
        final ActivityRecord activity = createActivityWithTask();
        assertTrue(activity.hasSavedState());

        ActivityRecord.activityResumedLocked(activity.appToken, false /* handleSplashScreenExit */);
        assertFalse(activity.hasSavedState());
        assertNull(activity.getSavedState());
    }

    /** Verify the behavior of {@link ActivityRecord#setSavedState(Bundle)}. */
    @Test
    public void testUpdateSavedState() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setSavedState(null /* savedState */);
        assertFalse(activity.hasSavedState());
        assertNull(activity.getSavedState());

        final Bundle savedState = new Bundle();
        savedState.putString("test", "string");
        activity.setSavedState(savedState);
        assertTrue(activity.hasSavedState());
        assertEquals(savedState, activity.getSavedState());
    }

    /** Verify the correct updates of saved state when activity client reports stop. */
    @Test
    public void testUpdateSavedState_activityStopped() {
        final ActivityRecord activity = createActivityWithTask();
        final Bundle savedState = new Bundle();
        savedState.putString("test", "string");
        final PersistableBundle persistentSavedState = new PersistableBundle();
        persistentSavedState.putString("persist", "string");

        // Set state to STOPPING, or ActivityRecord#activityStoppedLocked() call will be ignored.
        activity.setState(STOPPING, "test");
        activity.activityStopped(savedState, persistentSavedState, "desc");
        assertTrue(activity.hasSavedState());
        assertEquals(savedState, activity.getSavedState());
        assertEquals(persistentSavedState, activity.getPersistentSavedState());

        // Sending 'null' for saved state can only happen due to timeout, so previously stored saved
        // states should not be overridden.
        activity.setState(STOPPING, "test");
        activity.activityStopped(null /* savedState */, null /* persistentSavedState */, "desc");
        assertTrue(activity.hasSavedState());
        assertEquals(savedState, activity.getSavedState());
        assertEquals(persistentSavedState, activity.getPersistentSavedState());
    }

    /**
     * Verify that activity finish request is not performed if activity is finishing or is in
     * incorrect state.
     */
    @Test
    public void testFinishActivityIfPossible_cancelled() {
        final ActivityRecord activity = createActivityWithTask();
        // Mark activity as finishing
        activity.finishing = true;
        assertEquals("Duplicate finish request must be ignored", FINISH_RESULT_CANCELLED,
                activity.finishIfPossible("test", false /* oomAdj */));
        assertTrue(activity.finishing);
        assertTrue(activity.isInRootTaskLocked());

        // Remove activity from task
        activity.finishing = false;
        activity.onParentChanged(null /*newParent*/, activity.getTask());
        assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_CANCELLED,
                activity.finishIfPossible("test", false /* oomAdj */));
        assertFalse(activity.finishing);
    }

    /**
     * Verify that activity finish request is placed, but not executed immediately if activity is
     * not ready yet.
     */
    @Test
    public void testFinishActivityIfPossible_requested() {
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = false;
        assertEquals("Currently resumed activity must be prepared removal", FINISH_RESULT_REQUESTED,
                activity.finishIfPossible("test", false /* oomAdj */));
        assertTrue(activity.finishing);
        assertTrue(activity.isInRootTaskLocked());

        // First request to finish activity must schedule a "destroy" request to the client.
        // Activity must be removed from history after the client reports back or after timeout.
        activity.finishing = false;
        activity.setState(STOPPED, "test");
        assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REQUESTED,
                activity.finishIfPossible("test", false /* oomAdj */));
        assertTrue(activity.finishing);
        assertTrue(activity.isInRootTaskLocked());
    }

    /**
     * Verify that activity finish request removes activity immediately if it's ready.
     */
    @Test
    public void testFinishActivityIfPossible_removed() {
        final ActivityRecord activity = createActivityWithTask();
        // Prepare the activity record to be ready for immediate removal. It should be invisible and
        // have no process. Otherwise, request to finish it will send a message to client first.
        activity.setState(STOPPED, "test");
        activity.mVisibleRequested = false;
        activity.nowVisible = false;
        // Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() -
        // this will cause NPE when updating task's process.
        activity.app = null;

        // Put a visible activity on top, so the finishing activity doesn't have to wait until the
        // next activity reports idle to destroy it.
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask()).build();
        topActivity.mVisibleRequested = true;
        topActivity.nowVisible = true;
        topActivity.setState(RESUMED, "test");

        assertEquals("Activity outside of task/rootTask cannot be finished", FINISH_RESULT_REMOVED,
                activity.finishIfPossible("test", false /* oomAdj */));
        assertTrue(activity.finishing);
        assertFalse(activity.isInRootTaskLocked());
    }

    /**
     * Verify that when finishing the top focused activity on top display, the root task order
     * will be changed by adjusting focus.
     */
    @Test
    public void testFinishActivityIfPossible_adjustStackOrder() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        // Prepare the tasks with order (top to bottom): task, task1, task2.
        final Task task1 = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        task.moveToFront("test");
        // The task2 is needed here for moving back to simulate the
        // {@link DisplayContent#mPreferredTopFocusableStack} is cleared, so
        // {@link DisplayContent#getFocusedStack} will rely on the order of focusable-and-visible
        // tasks. Then when mActivity is finishing, its task will be invisible (no running
        // activities in the task) that is the key condition to verify.
        final Task task2 = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        task2.moveToBack("test", task2.getBottomMostTask());

        assertTrue(task.isTopRootTaskInDisplayArea());

        activity.setState(RESUMED, "test");
        activity.finishIfPossible(0 /* resultCode */, null /* resultData */,
                null /* resultGrants */, "test", false /* oomAdj */);

        assertTrue(task1.isTopRootTaskInDisplayArea());
    }

    /**
     * Verify that when finishing the top focused activity while root task was created by organizer,
     * the stack order will be changed by adjusting focus.
     */
    @Test
    public void testFinishActivityIfPossible_adjustStackOrderOrganizedRoot() {
        // Make mStack be a the root task that created by task organizer
        final Task rootableTask = new TaskBuilder(mSupervisor)
                .setCreateParentTask(true).setCreateActivity(true).build();
        final Task rootTask = rootableTask.getRootTask();
        rootTask.mCreatedByOrganizer = true;

        // Have two tasks (topRootableTask and rootableTask) as the children of rootTask.
        ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setParentTask(rootTask)
                .build();
        Task topRootableTask = topActivity.getTask();
        topRootableTask.moveToFront("test");
        assertTrue(rootTask.isTopRootTaskInDisplayArea());

        // Finish top activity and verify the next focusable rootable task has adjusted to top.
        topActivity.setState(RESUMED, "test");
        topActivity.finishIfPossible(0 /* resultCode */, null /* resultData */,
                null /* resultGrants */, "test", false /* oomAdj */);
        assertEquals(rootableTask, rootTask.getTopMostTask());
    }

    /**
     * Verify that when top focused activity is on secondary display, when finishing the top focused
     * activity on default display, the preferred top stack on default display should be changed by
     * adjusting focus.
     */
    @Test
    public void testFinishActivityIfPossible_PreferredTopStackChanged() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        final ActivityRecord topActivityOnNonTopDisplay =
                createActivityOnDisplay(true /* defaultDisplay */, null /* process */);
        Task topRootableTask = topActivityOnNonTopDisplay.getRootTask();
        topRootableTask.moveToFront("test");
        assertTrue(topRootableTask.isTopRootTaskInDisplayArea());
        assertEquals(topRootableTask, topActivityOnNonTopDisplay.getDisplayArea()
                .mPreferredTopFocusableRootTask);

        final ActivityRecord secondaryDisplayActivity =
                createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
        topRootableTask = secondaryDisplayActivity.getRootTask();
        topRootableTask.moveToFront("test");
        assertTrue(topRootableTask.isTopRootTaskInDisplayArea());
        assertEquals(topRootableTask,
                secondaryDisplayActivity.getDisplayArea().mPreferredTopFocusableRootTask);

        // The global top focus activity is on secondary display now.
        // Finish top activity on default display and verify the next preferred top focusable stack
        // on default display has changed.
        topActivityOnNonTopDisplay.setState(RESUMED, "test");
        topActivityOnNonTopDisplay.finishIfPossible(0 /* resultCode */, null /* resultData */,
                null /* resultGrants */, "test", false /* oomAdj */);
        assertEquals(task, task.getTopMostTask());
        assertEquals(task, activity.getDisplayArea().mPreferredTopFocusableRootTask);
    }

    /**
     * Verify that resumed activity is paused due to finish request.
     */
    @Test
    public void testFinishActivityIfPossible_resumedStartsPausing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = false;
        activity.setState(RESUMED, "test");
        assertEquals("Currently resumed activity must be paused before removal",
                FINISH_RESULT_REQUESTED, activity.finishIfPossible("test", false /* oomAdj */));
        assertEquals(PAUSING, activity.getState());
        verify(activity).setVisibility(eq(false));
        verify(activity.mDisplayContent).prepareAppTransition(eq(TRANSIT_CLOSE));
    }

    /**
     * Verify that finish request will be completed immediately for non-resumed activity.
     */
    @Test
    public void testFinishActivityIfPossible_nonResumedFinishCompletesImmediately() {
        final ActivityRecord activity = createActivityWithTask();
        final State[] states = {INITIALIZING, STARTED, PAUSED, STOPPING, STOPPED};
        for (State state : states) {
            activity.finishing = false;
            activity.setState(state, "test");
            reset(activity);
            assertEquals("Finish must be requested", FINISH_RESULT_REQUESTED,
                    activity.finishIfPossible("test", false /* oomAdj */));
            verify(activity).completeFinishing(anyString());
        }
    }

    /**
     * Verify that finishing will not be completed in PAUSING state.
     */
    @Test
    public void testFinishActivityIfPossible_pausing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = false;
        activity.setState(PAUSING, "test");
        assertEquals("Finish must be requested", FINISH_RESULT_REQUESTED,
                activity.finishIfPossible("test", false /* oomAdj */));
        verify(activity, never()).completeFinishing(anyString());
    }

    /**
     * Verify that finish request for resumed activity will prepare an app transition but not
     * execute it immediately.
     */
    @Test
    public void testFinishActivityIfPossible_visibleResumedPreparesAppTransition() {
        final ActivityRecord activity = createActivityWithTask();
        clearInvocations(activity.mDisplayContent);
        activity.finishing = false;
        activity.mVisibleRequested = true;
        activity.setState(RESUMED, "test");
        activity.finishIfPossible("test", false /* oomAdj */);

        verify(activity).setVisibility(eq(false));
        verify(activity.mDisplayContent).prepareAppTransition(eq(TRANSIT_CLOSE));
        verify(activity.mDisplayContent, never()).executeAppTransition();
    }

    /**
     * Verify that finish request for paused activity will prepare and execute an app transition.
     */
    @Test
    public void testFinishActivityIfPossible_visibleNotResumedExecutesAppTransition() {
        final ActivityRecord activity = createActivityWithTask();
        clearInvocations(activity.mDisplayContent);
        activity.finishing = false;
        activity.mVisibleRequested = true;
        activity.setState(PAUSED, "test");
        activity.finishIfPossible("test", false /* oomAdj */);

        verify(activity, atLeast(1)).setVisibility(eq(false));
        verify(activity.mDisplayContent).prepareAppTransition(eq(TRANSIT_CLOSE));
        verify(activity.mDisplayContent).executeAppTransition();
    }

    /**
     * Verify that finish request for non-visible activity will not prepare any transitions.
     */
    @Test
    public void testFinishActivityIfPossible_nonVisibleNoAppTransition() {
        registerTestTransitionPlayer();
        final ActivityRecord activity = createActivityWithTask();
        // Put an activity on top of test activity to make it invisible and prevent us from
        // accidentally resuming the topmost one again.
        new ActivityBuilder(mAtm).build();
        activity.mVisibleRequested = false;
        activity.setState(STOPPED, "test");

        activity.finishIfPossible("test", false /* oomAdj */);

        verify(activity.mDisplayContent, never()).prepareAppTransition(eq(TRANSIT_CLOSE));
        assertFalse(activity.inTransition());
    }

    /**
     * Verify that finish request for the last activity in a task will request a shell transition
     * with that task as a trigger.
     */
    @Test
    public void testFinishActivityIfPossible_lastInTaskRequestsTransitionWithTrigger() {
        final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = false;
        activity.mVisibleRequested = true;
        activity.setState(RESUMED, "test");
        activity.finishIfPossible("test", false /* oomAdj */);

        verify(activity).setVisibility(eq(false));
        assertEquals(activity.getTask().mTaskId, testPlayer.mLastRequest.getTriggerTask().taskId);
    }

    /**
     * Verify that when collecting activity to the existing close transition, it should not affect
     * ready state.
     */
    @Test
    public void testFinishActivityIfPossible_collectToExistingTransition() {
        final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(PAUSED, "test");
        activity.finishIfPossible("test", false /* oomAdj */);
        final Transition lastTransition = testPlayer.mLastTransit;
        assertTrue(lastTransition.allReady());
        assertTrue(activity.inTransition());

        // Collect another activity to the existing transition without changing ready state.
        final ActivityRecord activity2 = createActivityRecord(activity.getTask());
        activity2.setState(PAUSING, "test");
        activity2.finishIfPossible("test", false /* oomAdj */);
        assertTrue(activity2.inTransition());
        assertEquals(lastTransition, testPlayer.mLastTransit);
        assertTrue(lastTransition.allReady());
    }

    /**
     * Verify that complete finish request for non-finishing activity is invalid.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testCompleteFinishing_failNotFinishing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = false;
        activity.completeFinishing("test");
    }

    /**
     * Verify that complete finish request for resumed activity is invalid.
     */
    @Test(expected = IllegalArgumentException.class)
    public void testCompleteFinishing_failResumed() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(RESUMED, "test");
        activity.completeFinishing("test");
    }

    /**
     * Verify that finish request for pausing activity must be a no-op - activity will finish
     * once it completes pausing.
     */
    @Test
    public void testCompleteFinishing_pausing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(PAUSING, "test");
        activity.finishing = true;

        assertEquals("Activity must not be removed immediately - waiting for paused",
                activity, activity.completeFinishing("test"));
        assertEquals(PAUSING, activity.getState());
        verify(activity, never()).destroyIfPossible(anyString());
    }

    /**
     * Verify that finish request won't change the state of next top activity if the current
     * finishing activity doesn't need to be destroyed immediately. The case is usually like
     * from {@link Task#completePause(boolean, ActivityRecord)} to
     * {@link ActivityRecord#completeFinishing(String)}, so the complete-pause should take the
     * responsibility to resume the next activity with updating the state.
     */
    @Test
    public void testCompleteFinishing_keepStateOfNextInvisible() {
        final ActivityRecord currentTop = createActivityWithTask();
        final Task task = currentTop.getTask();

        currentTop.mVisibleRequested = currentTop.nowVisible = true;

        // Simulates that {@code currentTop} starts an existing activity from background (so its
        // state is stopped) and the starting flow just goes to place it at top.
        final Task nextStack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        final ActivityRecord nextTop = nextStack.getTopNonFinishingActivity();
        nextTop.setState(STOPPED, "test");

        task.setPausingActivity(currentTop);
        currentTop.finishing = true;
        currentTop.setState(PAUSED, "test");
        currentTop.completeFinishing("completePauseLocked");

        // Current top becomes stopping because it is visible and the next is invisible.
        assertEquals(STOPPING, currentTop.getState());
        // The state of next activity shouldn't be changed.
        assertEquals(STOPPED, nextTop.getState());
    }

    /**
     * Verify that finish bottom activity from a task won't boost it to top.
     */
    @Test
    public void testFinishBottomActivityIfPossible_noZBoost() {
        final ActivityRecord bottomActivity = createActivityWithTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(bottomActivity.getTask()).build();
        topActivity.mVisibleRequested = true;
        // simulating bottomActivity as a trampoline activity.
        bottomActivity.setState(RESUMED, "test");
        bottomActivity.finishIfPossible("test", false);
        assertFalse(bottomActivity.mNeedsZBoost);
    }

    /**
     * Verify that complete finish request for visible activity must be delayed before the next one
     * becomes visible.
     */
    @Test
    public void testCompleteFinishing_waitForNextVisible() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask()).build();
        topActivity.mVisibleRequested = true;
        topActivity.nowVisible = true;
        topActivity.finishing = true;
        topActivity.setState(PAUSED, "true");
        // Mark the bottom activity as not visible, so that we will wait for it before removing
        // the top one.
        activity.mVisibleRequested = false;
        activity.nowVisible = false;
        activity.setState(STOPPED, "test");

        assertEquals("Activity must not be removed immediately - waiting for next visible",
                topActivity, topActivity.completeFinishing("test"));
        assertEquals("Activity must be stopped to make next one visible", STOPPING,
                topActivity.getState());
        assertTrue("Activity must be stopped to make next one visible",
                topActivity.mTaskSupervisor.mStoppingActivities.contains(topActivity));
        verify(topActivity, never()).destroyIfPossible(anyString());
    }

    /**
     * Verify that complete finish request for top invisible activity must not be delayed while
     * sleeping, but next invisible activity must be resumed (and paused/stopped)
     */
    @Test
    public void testCompleteFinishing_noWaitForNextVisible_sleeping() {
        final ActivityRecord activity = createActivityWithTask();
        // Create a top activity on a new task
        final ActivityRecord topActivity = createActivityWithTask();
        mDisplayContent.setIsSleeping(true);
        doReturn(true).when(activity).shouldBeVisible();
        topActivity.mVisibleRequested = false;
        topActivity.nowVisible = false;
        topActivity.finishing = true;
        topActivity.setState(STOPPED, "true");

        // Mark the activity behind (on a separate task) as not visible
        activity.mVisibleRequested = false;
        activity.nowVisible = false;
        activity.setState(STOPPED, "test");

        clearInvocations(activity);
        topActivity.completeFinishing("test");
        verify(activity).setState(eq(RESUMED), any());
        verify(topActivity).destroyIfPossible(anyString());
    }

    /**
     * Verify that complete finish request for invisible activity must not be delayed.
     */
    @Test
    public void testCompleteFinishing_noWaitForNextVisible_alreadyInvisible() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask()).build();
        topActivity.mVisibleRequested = false;
        topActivity.nowVisible = false;
        topActivity.finishing = true;
        topActivity.setState(STOPPED, "true");
        // Mark the bottom activity as not visible, so that we would wait for it before removing
        // the top one.
        activity.mVisibleRequested = false;
        activity.nowVisible = false;
        activity.setState(STOPPED, "test");

        topActivity.completeFinishing("test");

        verify(topActivity).destroyIfPossible(anyString());
    }

    /**
     * Verify that paused finishing activity will be added to finishing list and wait for next one
     * to idle.
     */
    @Test
    public void testCompleteFinishing_waitForIdle() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask()).build();
        topActivity.mVisibleRequested = true;
        topActivity.nowVisible = true;
        topActivity.finishing = true;
        topActivity.setState(PAUSED, "true");
        // Mark the bottom activity as already visible, so that there is no need to wait for it.
        activity.mVisibleRequested = true;
        activity.nowVisible = true;
        activity.setState(RESUMED, "test");

        topActivity.completeFinishing("test");

        verify(topActivity).addToFinishingAndWaitForIdle();
    }

    /**
     * Verify that complete finish request for visible activity must not be delayed if the next one
     * is already visible and it's not the focused stack.
     */
    @Test
    public void testCompleteFinishing_noWaitForNextVisible_stopped() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask()).build();
        topActivity.mVisibleRequested = false;
        topActivity.nowVisible = false;
        topActivity.finishing = true;
        topActivity.setState(STOPPED, "true");
        // Mark the bottom activity as already visible, so that there is no need to wait for it.
        activity.mVisibleRequested = true;
        activity.nowVisible = true;
        activity.setState(RESUMED, "test");

        topActivity.completeFinishing("test");

        verify(topActivity).destroyIfPossible(anyString());
    }

    /**
     * Verify that complete finish request for visible activity must not be delayed if the next one
     * is already visible and it's not the focused stack.
     */
    @Test
    public void testCompleteFinishing_noWaitForNextVisible_nonFocusedStack() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask()).build();
        topActivity.mVisibleRequested = true;
        topActivity.nowVisible = true;
        topActivity.finishing = true;
        topActivity.setState(PAUSED, "true");
        // Mark the bottom activity as already visible, so that there is no need to wait for it.
        activity.mVisibleRequested = true;
        activity.nowVisible = true;
        activity.setState(RESUMED, "test");

        // Add another stack to become focused and make the activity there visible. This way it
        // simulates finishing in non-focused stack in split-screen.
        final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
        final ActivityRecord focusedActivity = stack.getTopMostActivity();
        focusedActivity.nowVisible = true;
        focusedActivity.mVisibleRequested = true;
        focusedActivity.setState(RESUMED, "test");
        stack.setResumedActivity(focusedActivity, "test");

        topActivity.completeFinishing("test");

        verify(topActivity).destroyIfPossible(anyString());
    }

    /**
     * Verify that complete finish request for a show-when-locked activity must ensure the
     * keyguard occluded state being updated.
     */
    @Test
    public void testCompleteFinishing_showWhenLocked() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        // Make keyguard locked and set the top activity show-when-locked.
        KeyguardController keyguardController = activity.mTaskSupervisor.getKeyguardController();
        doReturn(true).when(keyguardController).isKeyguardLocked();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
        topActivity.mVisibleRequested = true;
        topActivity.nowVisible = true;
        topActivity.setState(RESUMED, "true");
        doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
                any() /* starting */, anyInt() /* configChanges */,
                anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
        topActivity.setShowWhenLocked(true);

        // Verify the stack-top activity is occluded keyguard.
        assertEquals(topActivity, task.topRunningActivity());
        assertTrue(keyguardController.isDisplayOccluded(DEFAULT_DISPLAY));

        // Finish the top activity
        topActivity.setState(PAUSED, "true");
        topActivity.finishing = true;
        topActivity.completeFinishing("test");

        // Verify new top activity does not occlude keyguard.
        assertEquals(activity, task.topRunningActivity());
        assertFalse(keyguardController.isDisplayOccluded(DEFAULT_DISPLAY));
    }

    /**
     * Verify that complete finish request for an activity which the resume activity is translucent
     * must ensure the visibilities of activities being updated.
     */
    @Test
    public void testCompleteFinishing_ensureActivitiesVisible_withConditions() {
        testCompleteFinishing_ensureActivitiesVisible(false, PAUSED);
        testCompleteFinishing_ensureActivitiesVisible(false, STARTED);
        testCompleteFinishing_ensureActivitiesVisible(true, PAUSED);
        testCompleteFinishing_ensureActivitiesVisible(true, STARTED);
    }

    private void testCompleteFinishing_ensureActivitiesVisible(boolean diffTask,
            State secondActivityState) {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setTask(task).build();
        firstActivity.mVisibleRequested = false;
        firstActivity.nowVisible = false;
        firstActivity.setState(STOPPED, "test");

        final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(task).build();
        secondActivity.mVisibleRequested = true;
        secondActivity.nowVisible = true;
        secondActivity.setState(secondActivityState, "test");

        ActivityRecord translucentActivity;
        if (diffTask) {
            translucentActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        } else {
            translucentActivity = new ActivityBuilder(mAtm).setTask(task).build();
        }
        translucentActivity.mVisibleRequested = true;
        translucentActivity.nowVisible = true;
        translucentActivity.setState(RESUMED, "test");

        doReturn(true).when(firstActivity).occludesParent(true);
        doReturn(true).when(secondActivity).occludesParent(true);

        // Finish the second activity
        secondActivity.finishing = true;
        secondActivity.completeFinishing("test");
        verify(secondActivity.mDisplayContent).ensureActivitiesVisible(null /* starting */,
                0 /* configChanges */ , false /* preserveWindows */,
                true /* notifyClients */);

        // Finish the first activity
        firstActivity.finishing = true;
        firstActivity.mVisibleRequested = true;
        firstActivity.completeFinishing("test");
        verify(firstActivity.mDisplayContent, times(2)).ensureActivitiesVisible(null /* starting */,
                0 /* configChanges */ , false /* preserveWindows */,
                true /* notifyClients */);

        // Remove the translucent activity and clear invocations for next test
        translucentActivity.getTask().removeImmediately("test");
        clearInvocations(mDefaultDisplay);
    }

    /**
     * Verify destroy activity request completes successfully.
     */
    @Test
    public void testDestroyIfPossible() {
        final ActivityRecord activity = createActivityWithTask();
        doReturn(false).when(mRootWindowContainer)
                .resumeFocusedTasksTopActivities();
        activity.destroyIfPossible("test");

        assertEquals(DESTROYING, activity.getState());
        assertTrue(activity.finishing);
        verify(activity).destroyImmediately(anyString());
    }

    /**
     * Verify that complete finish request for visible activity must not destroy it immediately if
     * it is the last running activity on a display with a home stack. We must wait for home
     * activity to come up to avoid a black flash in this case.
     */
    @Test
    public void testDestroyIfPossible_lastActivityAboveEmptyHomeStack() {
        final ActivityRecord activity = createActivityWithTask();
        // Empty the home stack.
        final Task homeStack = activity.getDisplayArea().getRootHomeTask();
        homeStack.forAllLeafTasks((t) -> {
            homeStack.removeChild(t, "test");
        }, true /* traverseTopToBottom */);
        activity.finishing = true;
        doReturn(false).when(mRootWindowContainer)
                .resumeFocusedTasksTopActivities();

        // Try to destroy the last activity above the home stack.
        activity.destroyIfPossible("test");

        // Verify that the activity was not actually destroyed, but waits for next one to come up
        // instead.
        verify(activity, never()).destroyImmediately(anyString());
        assertEquals(FINISHING, activity.getState());
        assertTrue(activity.mTaskSupervisor.mFinishingActivities.contains(activity));
    }

    /**
     * Verify that complete finish request for visible activity must resume next home stack before
     * destroying it immediately if it is the last running activity on a display with a home stack.
     * We must wait for home activity to come up to avoid a black flash in this case.
     */
    @Test
    public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() {
        final ActivityRecord activity = createActivityWithTask();
        // Empty the home root task.
        final Task homeRootTask = activity.getDisplayArea().getRootHomeTask();
        homeRootTask.forAllLeafTasks((t) -> {
            homeRootTask.removeChild(t, "test");
        }, true /* traverseTopToBottom */);
        activity.setState(STARTED, "test");
        activity.finishing = true;
        activity.mVisibleRequested = true;

        // Try to finish the last activity above the home stack.
        activity.completeFinishing("test");

        // Verify that the activity is not destroyed immediately, but waits for next one to come up.
        verify(activity, never()).destroyImmediately(anyString());
        assertEquals(FINISHING, activity.getState());
        assertTrue(activity.mTaskSupervisor.mFinishingActivities.contains(activity));
    }

    /**
     * Test that the activity will be moved to destroying state and the message to destroy will be
     * sent to the client.
     */
    @Test
    public void testDestroyImmediately_hadApp_finishing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = true;
        activity.destroyImmediately("test");

        assertEquals(DESTROYING, activity.getState());
    }

    /**
     * Test that the activity will be moved to destroyed state immediately if it was not marked as
     * finishing before {@link ActivityRecord#destroyImmediately(String)}.
     */
    @Test
    public void testDestroyImmediately_hadApp_notFinishing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.finishing = false;
        activity.destroyImmediately("test");

        assertEquals(DESTROYED, activity.getState());
    }

    /**
     * Test that an activity with no process attached and that is marked as finishing will be
     * removed from task when {@link ActivityRecord#destroyImmediately(String)} is called.
     */
    @Test
    public void testDestroyImmediately_noApp_finishing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.app = null;
        activity.finishing = true;
        final Task task = activity.getTask();

        activity.destroyImmediately("test");

        assertEquals(DESTROYED, activity.getState());
        assertNull(activity.getTask());
        assertEquals(0, task.getChildCount());
    }

    /**
     * Test that an activity with no process attached and that is not marked as finishing will be
     * marked as DESTROYED but not removed from task.
     */
    @Test
    public void testDestroyImmediately_noApp_notFinishing() {
        final ActivityRecord activity = createActivityWithTask();
        activity.app = null;
        activity.finishing = false;
        final Task task = activity.getTask();

        activity.destroyImmediately("test");

        assertEquals(DESTROYED, activity.getState());
        assertEquals(task, activity.getTask());
        assertEquals(1, task.getChildCount());
    }

    /**
     * Test that an activity will not be destroyed if it is marked as non-destroyable.
     */
    @Test
    public void testSafelyDestroy_nonDestroyable() {
        final ActivityRecord activity = createActivityWithTask();
        doReturn(false).when(activity).isDestroyable();

        activity.safelyDestroy("test");

        verify(activity, never()).destroyImmediately(anyString());
    }

    /**
     * Test that an activity will not be destroyed if it is marked as non-destroyable.
     */
    @Test
    public void testSafelyDestroy_destroyable() {
        final ActivityRecord activity = createActivityWithTask();
        doReturn(true).when(activity).isDestroyable();

        activity.safelyDestroy("test");

        verify(activity).destroyImmediately(anyString());
    }

    @Test
    public void testRemoveImmediately() {
        final Consumer<Consumer<ActivityRecord>> test = setup -> {
            final ActivityRecord activity = createActivityWithTask();
            final WindowProcessController wpc = activity.app;
            setup.accept(activity);
            activity.getTask().removeImmediately("test");
            try {
                verify(mAtm.getLifecycleManager()).scheduleTransaction(any(), eq(activity.appToken),
                        isA(DestroyActivityItem.class));
            } catch (RemoteException ignored) {
            }
            assertNull(activity.app);
            assertEquals(DESTROYED, activity.getState());
            assertFalse(wpc.hasActivities());
        };
        test.accept(activity -> activity.setState(RESUMED, "test"));
        test.accept(activity -> activity.finishing = true);
    }

    @Test
    public void testRemoveFromHistory() {
        final ActivityRecord activity = createActivityWithTask();
        final Task rootTask = activity.getRootTask();
        final Task task = activity.getTask();
        final WindowProcessController wpc = activity.app;
        assertTrue(wpc.hasActivities());

        activity.removeFromHistory("test");

        assertEquals(DESTROYED, activity.getState());
        assertNull(activity.app);
        assertNull(activity.getTask());
        assertFalse(wpc.hasActivities());
        assertEquals(0, task.getChildCount());
        assertEquals(task.getRootTask(), task);
        assertEquals(0, rootTask.getChildCount());
    }

    /**
     * Test that it's not allowed to call {@link ActivityRecord#destroyed(String)} if activity is
     * not in destroying or destroyed state.
     */
    @Test(expected = IllegalStateException.class)
    public void testDestroyed_notDestroying() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(STOPPED, "test");
        activity.destroyed("test");
    }

    /**
     * Test that {@link ActivityRecord#destroyed(String)} can be called if an activity is destroying
     */
    @Test
    public void testDestroyed_destroying() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(DESTROYING, "test");
        activity.destroyed("test");

        verify(activity).removeFromHistory(anyString());
    }

    /**
     * Test that {@link ActivityRecord#destroyed(String)} can be called if an activity is destroyed.
     */
    @Test
    public void testDestroyed_destroyed() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(DESTROYED, "test");
        activity.destroyed("test");

        verify(activity).removeFromHistory(anyString());
    }

    @Test
    public void testActivityOverridesProcessConfig() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        assertTrue(wpc.registeredForActivityConfigChanges());
        assertFalse(wpc.registeredForDisplayAreaConfigChanges());

        final ActivityRecord secondaryDisplayActivity =
                createActivityOnDisplay(false /* defaultDisplay */, null /* process */);

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, activity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
        assertNotEquals(activity.getConfiguration(),
                secondaryDisplayActivity.getConfiguration());
    }

    @Test
    public void testActivityOverridesProcessConfig_TwoActivities() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        assertTrue(wpc.registeredForActivityConfigChanges());

        final Task firstTaskRecord = activity.getTask();
        final ActivityRecord secondActivityRecord =
                new ActivityBuilder(mAtm).setTask(firstTaskRecord).setUseProcess(wpc).build();

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
    }

    @Test
    public void testActivityOverridesProcessConfig_TwoActivities_SecondaryDisplay() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        assertTrue(wpc.registeredForActivityConfigChanges());

        final ActivityRecord secondActivityRecord =
                new ActivityBuilder(mAtm).setTask(activity.getTask()).setUseProcess(wpc).build();

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
    }

    @Test
    public void testActivityOverridesProcessConfig_TwoActivities_DifferentTasks() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        assertTrue(wpc.registeredForActivityConfigChanges());

        final ActivityRecord secondActivityRecord =
                createActivityOnDisplay(true /* defaultDisplay */, wpc);

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
    }

    @Test
    public void testActivityOnCancelFixedRotationTransform() {
        final ActivityRecord activity = createActivityWithTask();
        final DisplayRotation displayRotation = activity.mDisplayContent.getDisplayRotation();
        spyOn(displayRotation);

        final DisplayContent display = activity.mDisplayContent;
        final int originalRotation = display.getRotation();

        // Make {@link DisplayContent#sendNewConfiguration} not apply rotation immediately.
        doReturn(true).when(displayRotation).isWaitingForRemoteRotation();
        doReturn((originalRotation + 1) % 4).when(displayRotation).rotationForOrientation(
                anyInt() /* orientation */, anyInt() /* lastRotation */);
        // Set to visible so the activity can freeze the screen.
        activity.setVisibility(true);

        display.rotateInDifferentOrientationIfNeeded(activity);
        display.setFixedRotationLaunchingAppUnchecked(activity);
        displayRotation.updateRotationUnchecked(true /* forceUpdate */);

        assertTrue(displayRotation.isRotatingSeamlessly());

        // The launching rotated app should not be cleared when waiting for remote rotation.
        display.continueUpdateOrientationForDiffOrienLaunchingApp();
        assertTrue(display.isFixedRotationLaunchingApp(activity));

        // Simulate the rotation has been updated to previous one, e.g. sensor updates before the
        // remote rotation is completed.
        doReturn(originalRotation).when(displayRotation).rotationForOrientation(
                anyInt() /* orientation */, anyInt() /* lastRotation */);
        display.updateOrientation();

        final DisplayInfo rotatedInfo = activity.getFixedRotationTransformDisplayInfo();
        activity.finishFixedRotationTransform();
        final ScreenRotationAnimation rotationAnim = display.getRotationAnimation();
        assertNotNull(rotationAnim);
        rotationAnim.setRotation(display.getPendingTransaction(), originalRotation);

        // Because the display doesn't rotate, the rotated activity needs to cancel the fixed
        // rotation. There should be a rotation animation to cover the change of activity.
        verify(activity).onCancelFixedRotationTransform(rotatedInfo.rotation);
        assertTrue(activity.isFreezingScreen());
        assertFalse(displayRotation.isRotatingSeamlessly());
        assertTrue(rotationAnim.isRotating());

        // Simulate the remote rotation has completed and the configuration doesn't change, then
        // the rotated activity should also be restored by clearing the transform.
        displayRotation.updateRotationUnchecked(true /* forceUpdate */);
        doReturn(false).when(displayRotation).isWaitingForRemoteRotation();
        clearInvocations(activity);
        display.setFixedRotationLaunchingAppUnchecked(activity);
        display.sendNewConfiguration();

        assertFalse(display.hasTopFixedRotationLaunchingApp());
        assertFalse(activity.hasFixedRotationTransform());

        // Simulate that the activity requests the same orientation as display.
        activity.setOrientation(display.getConfiguration().orientation);
        // Skip the real freezing.
        activity.mVisibleRequested = false;
        clearInvocations(activity);
        activity.onCancelFixedRotationTransform(originalRotation);
        // The implementation of cancellation must be executed.
        verify(activity).startFreezingScreen(originalRotation);
    }

    @Test
    public void testIsSnapshotCompatible() {
        final ActivityRecord activity = createActivityWithTask();
        final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
                .setTopActivityComponent(activity.mActivityComponent)
                .setRotation(activity.getWindowConfiguration().getRotation())
                .build();

        assertTrue(activity.isSnapshotCompatible(snapshot));

        setRotatedScreenOrientationSilently(activity);

        assertFalse(activity.isSnapshotCompatible(snapshot));
    }

    /**
     * Test that the snapshot should be obsoleted if the top activity changed.
     */
    @Test
    public void testIsSnapshotCompatibleTopActivityChanged() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
                .setTask(activity.getTask())
                .setOnTop(true)
                .build();
        final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
                .setTopActivityComponent(secondActivity.mActivityComponent)
                .build();

        assertTrue(secondActivity.isSnapshotCompatible(snapshot));

        // Emulate the top activity changed.
        assertFalse(activity.isSnapshotCompatible(snapshot));
    }

    @Test
    public void testFixedRotationSnapshotStartingWindow() {
        final ActivityRecord activity = createActivityWithTask();
        // TaskSnapshotSurface requires a fullscreen opaque window.
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
        params.width = params.height = WindowManager.LayoutParams.MATCH_PARENT;
        final TestWindowState w = new TestWindowState(
                mAtm.mWindowManager, mock(Session.class), new TestIWindow(), params, activity);
        activity.addWindow(w);

        // Assume the activity is launching in different rotation, and there was an available
        // snapshot accepted by {@link Activity#isSnapshotCompatible}.
        final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
                .setRotation((activity.getWindowConfiguration().getRotation() + 1) % 4)
                .build();
        setRotatedScreenOrientationSilently(activity);
        activity.setVisible(false);

        final IWindowSession session = WindowManagerGlobal.getWindowSession();
        spyOn(session);
        try {
            // Return error to skip unnecessary operation.
            doReturn(WindowManagerGlobal.ADD_STARTING_NOT_NEEDED).when(session).addToDisplay(
                    any() /* window */,  any() /* attrs */,
                    anyInt() /* viewVisibility */, anyInt() /* displayId */,
                    any() /* requestedVisibilities */, any() /* outInputChannel */,
                    any() /* outInsetsState */, any() /* outActiveControls */);
            mAtm.mWindowManager.mStartingSurfaceController
                    .createTaskSnapshotSurface(activity, snapshot);
        } catch (RemoteException ignored) {
        } finally {
            reset(session);
        }

        // Because the rotation of snapshot and the corresponding top activity are different, fixed
        // rotation should be applied when creating snapshot surface if the display rotation may be
        // changed according to the activity orientation.
        assertTrue(activity.hasFixedRotationTransform());
        assertTrue(activity.mDisplayContent.isFixedRotationLaunchingApp(activity));
    }

    /**
     * Sets orientation without notifying the parent to simulate that the display has not applied
     * the requested orientation yet.
     */
    static void setRotatedScreenOrientationSilently(ActivityRecord r) {
        final int rotatedOrentation = r.getConfiguration().orientation == ORIENTATION_PORTRAIT
                ? SCREEN_ORIENTATION_LANDSCAPE
                : SCREEN_ORIENTATION_PORTRAIT;
        doReturn(false).when(r).onDescendantOrientationChanged(any());
        r.setOrientation(rotatedOrentation);
    }

    @Test
    public void testActivityOnDifferentDisplayUpdatesProcessOverride() {
        final ActivityRecord secondaryDisplayActivity =
                createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
        final WindowProcessController wpc = secondaryDisplayActivity.app;
        assertTrue(wpc.registeredForActivityConfigChanges());

        final ActivityRecord secondActivityRecord =
                createActivityOnDisplay(true /* defaultDisplay */, wpc);

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
        assertFalse(wpc.registeredForDisplayAreaConfigChanges());
    }

    @Test
    public void testActivityReparentChangesProcessOverride() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        final Task initialTask = activity.getTask();
        final Configuration initialConf =
                new Configuration(activity.getMergedOverrideConfiguration());
        assertEquals(0, activity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
        assertTrue(wpc.registeredForActivityConfigChanges());

        // Create a new task with custom config to reparent the activity to.
        final Task newTask = new TaskBuilder(mSupervisor).build();
        final Configuration newConfig = newTask.getConfiguration();
        newConfig.densityDpi += 100;
        newTask.onRequestedOverrideConfigurationChanged(newConfig);
        assertEquals(newTask.getConfiguration().densityDpi, newConfig.densityDpi);

        // Reparent the activity and verify that config override changed.
        activity.reparent(newTask, 0 /* top */, "test");
        assertEquals(activity.getConfiguration().densityDpi, newConfig.densityDpi);
        assertEquals(activity.getMergedOverrideConfiguration().densityDpi, newConfig.densityDpi);

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertNotEquals(initialConf, wpc.getRequestedOverrideConfiguration());
        assertEquals(0, activity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
    }

    @Test
    public void testActivityReparentDoesntClearProcessOverride_TwoActivities() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowProcessController wpc = activity.app;
        final Configuration initialConf =
                new Configuration(activity.getMergedOverrideConfiguration());
        final Task initialTask = activity.getTask();
        final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(initialTask)
                .setUseProcess(wpc).build();

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));

        // Create a new task with custom config to reparent the second activity to.
        final Task newTask = new TaskBuilder(mSupervisor).build();
        final Configuration newConfig = newTask.getConfiguration();
        newConfig.densityDpi += 100;
        newTask.onRequestedOverrideConfigurationChanged(newConfig);

        // Reparent the activity and verify that config override changed.
        secondActivity.reparent(newTask, 0 /* top */, "test");

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
        assertNotEquals(initialConf, wpc.getRequestedOverrideConfiguration());

        // Reparent the first activity and verify that config override didn't change.
        activity.reparent(newTask, 1 /* top */, "test");
        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
        assertNotEquals(initialConf, wpc.getRequestedOverrideConfiguration());
    }

    @Test
    public void testActivityDestroyDoesntChangeProcessOverride() {
        final ActivityRecord firstActivity =
                createActivityOnDisplay(true /* defaultDisplay */, null /* process */);
        final WindowProcessController wpc = firstActivity.app;
        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, firstActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));

        final ActivityRecord secondActivity =
                createActivityOnDisplay(false /* defaultDisplay */, wpc);
        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, secondActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));

        final ActivityRecord thirdActivity =
                createActivityOnDisplay(false /* defaultDisplay */, wpc);
        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, thirdActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));

        secondActivity.destroyImmediately("");

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, thirdActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));

        firstActivity.destroyImmediately("");

        assertTrue(wpc.registeredForActivityConfigChanges());
        assertEquals(0, thirdActivity.getMergedOverrideConfiguration()
                .diff(wpc.getRequestedOverrideConfiguration()));
    }

    @Test
    public void testFullscreenWindowCanTurnScreenOn() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        doReturn(true).when(activity).getTurnScreenOnFlag();

        assertTrue(activity.canTurnScreenOn());
    }

    @Test
    public void testFreeformWindowCanTurnScreenOn() {
        final ActivityRecord activity = createActivityWithTask();
        final Task task = activity.getTask();
        task.setWindowingMode(WINDOWING_MODE_FREEFORM);
        doReturn(true).when(activity).getTurnScreenOnFlag();

        assertTrue(activity.canTurnScreenOn());
    }

    @Test
    public void testGetLockTaskLaunchMode() {
        final ActivityRecord activity = createActivityWithTask();
        final ActivityOptions options = ActivityOptions.makeBasic().setLockTaskEnabled(true);
        activity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
        assertEquals(LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED,
                ActivityRecord.getLockTaskLaunchMode(activity.info, options));

        activity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_ALWAYS;
        assertEquals(LOCK_TASK_LAUNCH_MODE_DEFAULT,
                ActivityRecord.getLockTaskLaunchMode(activity.info, null /*options*/));

        activity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_NEVER;
        assertEquals(LOCK_TASK_LAUNCH_MODE_DEFAULT,
                ActivityRecord.getLockTaskLaunchMode(activity.info, null /*options*/));

        activity.info.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
        activity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_ALWAYS;
        assertEquals(LOCK_TASK_LAUNCH_MODE_ALWAYS,
                ActivityRecord.getLockTaskLaunchMode(activity.info, null /*options*/));

        activity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_NEVER;
        assertEquals(LOCK_TASK_LAUNCH_MODE_NEVER,
                ActivityRecord.getLockTaskLaunchMode(activity.info, null /*options*/));

    }

    @Test
    public void testProcessInfoUpdateWhenSetState() {
        final ActivityRecord activity = createActivityWithTask();
        activity.setState(INITIALIZING, "test");
        spyOn(activity.app);
        verifyProcessInfoUpdate(activity, RESUMED,
                true /* shouldUpdate */, true /* activityChange */);
        verifyProcessInfoUpdate(activity, PAUSED,
                false /* shouldUpdate */, false /* activityChange */);
        verifyProcessInfoUpdate(activity, STOPPED,
                false /* shouldUpdate */, false /* activityChange */);
        verifyProcessInfoUpdate(activity, STARTED,
                true /* shouldUpdate */, true /* activityChange */);

        activity.app.removeActivity(activity, true /* keepAssociation */);
        verifyProcessInfoUpdate(activity, DESTROYING,
                true /* shouldUpdate */, false /* activityChange */);
        verifyProcessInfoUpdate(activity, DESTROYED,
                true /* shouldUpdate */, false /* activityChange */);
    }

    @Test
    public void testSupportsSplitScreenWindowingMode() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
                .build();

        // Not allow non-resizable
        mAtm.mForceResizableActivities = false;
        mAtm.mSupportsNonResizableMultiWindow = -1;
        mAtm.mDevEnableNonResizableMultiWindow = false;
        assertFalse(activity.supportsSplitScreenWindowingMode());

        // Force resizable
        mAtm.mForceResizableActivities = true;
        mAtm.mSupportsNonResizableMultiWindow = -1;
        mAtm.mDevEnableNonResizableMultiWindow = false;
        assertTrue(activity.supportsSplitScreenWindowingMode());

        // Use development option to allow non-resizable
        mAtm.mForceResizableActivities = false;
        mAtm.mSupportsNonResizableMultiWindow = -1;
        mAtm.mDevEnableNonResizableMultiWindow = true;
        assertTrue(activity.supportsSplitScreenWindowingMode());

        // Always allow non-resizable
        mAtm.mForceResizableActivities = false;
        mAtm.mSupportsNonResizableMultiWindow = 1;
        mAtm.mDevEnableNonResizableMultiWindow = false;
        assertTrue(activity.supportsSplitScreenWindowingMode());
    }

    @Test
    public void testSupportsFreeform() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
                .build();

        // Not allow non-resizable
        mAtm.mForceResizableActivities = false;
        mAtm.mSupportsNonResizableMultiWindow = -1;
        mAtm.mDevEnableNonResizableMultiWindow = false;
        assertFalse(activity.supportsFreeform());

        // Force resizable
        mAtm.mForceResizableActivities = true;
        mAtm.mSupportsNonResizableMultiWindow = -1;
        mAtm.mDevEnableNonResizableMultiWindow = false;
        assertTrue(activity.supportsFreeform());

        // Use development option to allow non-resizable
        mAtm.mForceResizableActivities = false;
        mAtm.mSupportsNonResizableMultiWindow = -1;
        mAtm.mDevEnableNonResizableMultiWindow = true;
        assertTrue(activity.supportsFreeform());

        // Always allow non-resizable
        mAtm.mForceResizableActivities = false;
        mAtm.mSupportsNonResizableMultiWindow = 1;
        mAtm.mDevEnableNonResizableMultiWindow = false;
        assertTrue(activity.supportsFreeform());
    }

    @Test
    public void testSupportsPictureInPicture() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE)
                .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE)
                .build();

        // Device not supports PIP
        mAtm.mSupportsPictureInPicture = false;
        assertFalse(activity.supportsPictureInPicture());

        // Device and app support PIP
        mAtm.mSupportsPictureInPicture = true;
        assertTrue(activity.supportsPictureInPicture());

        // Activity not supports PIP
        activity.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
        assertFalse(activity.supportsPictureInPicture());
    }

    private void verifyProcessInfoUpdate(ActivityRecord activity, State state,
            boolean shouldUpdate, boolean activityChange) {
        reset(activity.app);
        activity.setState(state, "test");
        verify(activity.app, times(shouldUpdate ? 1 : 0)).updateProcessInfo(anyBoolean(),
                eq(activityChange), anyBoolean(), anyBoolean());
    }

    private ActivityRecord createActivityWithTask() {
        return new ActivityBuilder(mAtm).setCreateTask(true).setOnTop(true).build();
    }

    private ActivityRecord createActivityWith2LevelTask() {
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateParentTask(true).setCreateActivity(true).build();
        return task.getTopNonFinishingActivity();
    }

    /**
     * Creates an activity on display. For non-default display request it will also create a new
     * display with custom DisplayInfo.
     */
    private ActivityRecord createActivityOnDisplay(boolean defaultDisplay,
            WindowProcessController process) {
        final DisplayContent display;
        if (defaultDisplay) {
            display = mRootWindowContainer.getDefaultDisplay();
        } else {
            display = new TestDisplayContent.Builder(mAtm, 2000, 1000).setDensityDpi(300)
                    .setPosition(DisplayContent.POSITION_TOP).build();
        }
        final Task task = new TaskBuilder(mSupervisor).setDisplay(display).build();
        return new ActivityBuilder(mAtm).setTask(task).setUseProcess(process).build();
    }

    @Test
    @Presubmit
    public void testAddWindow_Order() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        assertEquals(0, activity.getChildCount());

        final WindowState win1 = createWindow(null, TYPE_APPLICATION, activity, "win1");
        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
                "startingWin");
        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, activity, "baseWin");
        final WindowState win4 = createWindow(null, TYPE_APPLICATION, activity, "win4");

        // Should not contain the windows that were added above.
        assertEquals(4, activity.getChildCount());
        assertTrue(activity.mChildren.contains(win1));
        assertTrue(activity.mChildren.contains(startingWin));
        assertTrue(activity.mChildren.contains(baseWin));
        assertTrue(activity.mChildren.contains(win4));

        // The starting window should be on-top of all other windows.
        assertEquals(startingWin, activity.mChildren.peekLast());

        // The base application window should be below all other windows.
        assertEquals(baseWin, activity.mChildren.peekFirst());
        activity.removeImmediately();
    }

    @Test
    @Presubmit
    public void testFindMainWindow() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        assertNull(activity.findMainWindow());

        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "window1");
        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, activity, "window11");
        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, activity, "window12");
        assertEquals(window1, activity.findMainWindow());
        window1.mAnimatingExit = true;
        assertEquals(window1, activity.findMainWindow());
        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, activity,
                "window2");
        assertEquals(window2, activity.findMainWindow());
        activity.removeImmediately();
    }

    @Test
    @Presubmit
    public void testGetTopFullscreenOpaqueWindow() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        assertNull(activity.getTopFullscreenOpaqueWindow());

        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "window1");
        final WindowState window11 = createWindow(null, TYPE_APPLICATION, activity, "window11");
        final WindowState window12 = createWindow(null, TYPE_APPLICATION, activity, "window12");
        assertEquals(window12, activity.getTopFullscreenOpaqueWindow());
        window12.mAttrs.width = 500;
        assertEquals(window11, activity.getTopFullscreenOpaqueWindow());
        window11.mAttrs.width = 500;
        assertEquals(window1, activity.getTopFullscreenOpaqueWindow());
        window1.mAttrs.alpha = 0f;
        assertNull(activity.getTopFullscreenOpaqueWindow());
        activity.removeImmediately();
    }

    @UseTestDisplay(addWindows = W_ACTIVITY)
    @Test
    public void testLandscapeSeascapeRotationByApp() {
        final Task task = new TaskBuilder(mSupervisor)
                .setDisplay(mDisplayContent).setCreateActivity(true).build();
        final ActivityRecord activity = task.getTopNonFinishingActivity();
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                TYPE_BASE_APPLICATION);
        attrs.setTitle("AppWindow");
        final TestWindowState appWindow = createWindowState(attrs, activity);
        activity.addWindow(appWindow);
        spyOn(appWindow);
        doNothing().when(appWindow).onStartFreezingScreen();

        // Set initial orientation and update.
        activity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
        mDisplayContent.updateOrientation(
                mDisplayContent.getRequestedOverrideConfiguration(),
                null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation());
        appWindow.mResizeReported = false;

        // Update the orientation to perform 180 degree rotation and check that resize was reported.
        activity.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        mDisplayContent.updateOrientation(
                mDisplayContent.getRequestedOverrideConfiguration(),
                null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
        // In this test, DC will not get config update. Set the waiting flag to false.
        mDisplayContent.mWaitingForConfig = false;
        mWm.mRoot.performSurfacePlacement();
        assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
        assertTrue(appWindow.mResizeReported);
        appWindow.removeImmediately();
    }

    @UseTestDisplay(addWindows = W_ACTIVITY)
    @Test
    public void testLandscapeSeascapeRotationByPolicy() {
        final Task task = new TaskBuilder(mSupervisor)
                .setDisplay(mDisplayContent).setCreateActivity(true).build();
        final ActivityRecord activity = task.getTopNonFinishingActivity();
        // This instance has been spied in {@link TestDisplayContent}.
        final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();

        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                TYPE_BASE_APPLICATION);
        attrs.setTitle("RotationByPolicy");
        final TestWindowState appWindow = createWindowState(attrs, activity);
        activity.addWindow(appWindow);
        spyOn(appWindow);
        doNothing().when(appWindow).onStartFreezingScreen();

        // Set initial orientation and update.
        performRotation(displayRotation, Surface.ROTATION_90);
        appWindow.mResizeReported = false;

        // Update the rotation to perform 180 degree rotation and check that resize was reported.
        performRotation(displayRotation, Surface.ROTATION_270);
        assertTrue(appWindow.mResizeReported);

        appWindow.removeImmediately();
    }

    private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
        doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
        mWm.updateRotation(false, false);
    }

    @Test
    @Presubmit
    public void testGetOrientation() {
        // ActivityBuilder will resume top activities and cause the activity been added into
        // opening apps list. Since this test is focus on the effect of visible on getting
        // orientation, we skip app transition to avoid interference.
        doNothing().when(mDisplayContent).prepareAppTransition(anyInt());
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        activity.setVisible(true);

        activity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);

        activity.setOccludesParent(false);
        // Can specify orientation if app doesn't occludes parent.
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, activity.getOrientation());

        activity.setOccludesParent(true);
        activity.setVisible(false);
        activity.mVisibleRequested = false;
        // Can not specify orientation if app isn't visible even though it occludes parent.
        assertEquals(SCREEN_ORIENTATION_UNSET, activity.getOrientation());
        // Can specify orientation if the current orientation candidate is orientation behind.
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE,
                activity.getOrientation(SCREEN_ORIENTATION_BEHIND));
    }

    @Test
    @Presubmit
    public void testKeyguardFlagsDuringRelaunch() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
                TYPE_BASE_APPLICATION);
        attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD;
        attrs.setTitle("AppWindow");
        final TestWindowState appWindow = createWindowState(attrs, activity);

        // Add window with show when locked flag
        activity.addWindow(appWindow);
        assertTrue(activity.containsShowWhenLockedWindow()
                && activity.containsDismissKeyguardWindow());

        // Start relaunching
        activity.startRelaunching();
        assertTrue(activity.containsShowWhenLockedWindow()
                && activity.containsDismissKeyguardWindow());

        // Remove window and make sure that we still report back flag
        activity.removeChild(appWindow);
        assertTrue(activity.containsShowWhenLockedWindow()
                && activity.containsDismissKeyguardWindow());

        // Finish relaunching and ensure flag is now not reported
        activity.finishRelaunching();
        assertFalse(activity.containsShowWhenLockedWindow()
                || activity.containsDismissKeyguardWindow());
    }

    @Test
    public void testStuckExitingWindow() {
        final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
                "closingWindow");
        closingWindow.mAnimatingExit = true;
        closingWindow.mRemoveOnExit = true;
        closingWindow.mActivityRecord.commitVisibility(
                false /* visible */, true /* performLayout */);

        // We pretended that we were running an exit animation, but that should have been cleared up
        // by changing visibility of ActivityRecord
        closingWindow.removeIfPossible();
        assertTrue(closingWindow.mRemoved);
    }

    @Test
    public void testSetOrientation() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        activity.setVisible(true);

        // Assert orientation is unspecified to start.
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, activity.getOrientation());

        activity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, activity.getOrientation());

        mDisplayContent.removeAppToken(activity.token);
        // Assert orientation is unset to after container is removed.
        assertEquals(SCREEN_ORIENTATION_UNSET, activity.getOrientation());

        // Reset display frozen state
        mWm.mDisplayFrozen = false;
    }

    @UseTestDisplay
    @Test
    public void testRespectTopFullscreenOrientation() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final Configuration displayConfig = activity.mDisplayContent.getConfiguration();
        final Configuration activityConfig = activity.getConfiguration();
        activity.setOrientation(SCREEN_ORIENTATION_PORTRAIT);

        assertEquals(Configuration.ORIENTATION_PORTRAIT, displayConfig.orientation);
        assertEquals(Configuration.ORIENTATION_PORTRAIT, activityConfig.orientation);

        final ActivityRecord topActivity = createActivityRecord(activity.getTask());
        topActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);

        assertEquals(Configuration.ORIENTATION_LANDSCAPE, displayConfig.orientation);
        // Although the activity requested portrait, it is not the top activity that determines
        // the display orientation. So it should be able to inherit the orientation from parent.
        // Otherwise its configuration will be inconsistent that its orientation is portrait but
        // other screen configurations are in landscape, e.g. screenWidthDp, screenHeightDp, and
        // window configuration.
        assertEquals(Configuration.ORIENTATION_LANDSCAPE, activityConfig.orientation);
    }

    @UseTestDisplay
    @Test
    public void testReportOrientationChange() {
        final Task task = new TaskBuilder(mSupervisor)
                .setDisplay(mDisplayContent).setCreateActivity(true).build();
        final ActivityRecord activity = task.getTopNonFinishingActivity();
        activity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);

        mDisplayContent.getDisplayRotation().setFixedToUserRotation(
                IWindowManager.FIXED_TO_USER_ROTATION_ENABLED);
        reset(task);
        activity.reportDescendantOrientationChangeIfNeeded();
        verify(task, atLeast(1)).onConfigurationChanged(any(Configuration.class));
    }

    @Test
    public void testCreateRemoveStartingWindow() {
        registerTestStartingWindowOrganizer();
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        activity.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();
        assertHasStartingWindow(activity);
        activity.removeStartingWindow();
        waitUntilHandlersIdle();
        assertNoStartingWindow(activity);
    }

    private void testLegacySplashScreen(int targetSdk, int verifyType) {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        activity.mTargetSdk = targetSdk;
        activity.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();
        assertHasStartingWindow(activity);
        assertEquals(activity.mStartingData.mTypeParams & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN,
                verifyType);
        activity.removeStartingWindow();
        waitUntilHandlersIdle();
        assertNoStartingWindow(activity);
    }

    @Test
    public void testCreateRemoveLegacySplashScreenWindow() {
        registerTestStartingWindowOrganizer();
        DeviceConfig.Properties properties = DeviceConfig.getProperties(
                DeviceConfig.NAMESPACE_WINDOW_MANAGER);
        try {
            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                    "splash_screen_exception_list", DEFAULT_COMPONENT_PACKAGE_NAME, false);
            testLegacySplashScreen(Build.VERSION_CODES.R, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
            testLegacySplashScreen(Build.VERSION_CODES.S, 0);
        } finally {
            try {
                DeviceConfig.setProperties(properties);
            } catch (DeviceConfig.BadConfigException e) {
                Assert.fail(e.getMessage());
            }
        }
    }

    @Test
    public void testTransferStartingWindow() {
        registerTestStartingWindowOrganizer();
        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true)
                .setVisible(false).build();
        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true)
                .setVisible(false).build();
        activity1.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();
        activity2.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1,
                true, true, false, true, false, false);
        waitUntilHandlersIdle();
        assertFalse(mDisplayContent.mSkipAppTransitionAnimation);
        assertNoStartingWindow(activity1);
        assertHasStartingWindow(activity2);
    }

    @Test
    public void testTransferStartingWindowWhileCreating() {
        final TestStartingWindowOrganizer organizer = registerTestStartingWindowOrganizer();
        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
        organizer.setRunnableWhenAddingSplashScreen(
                () -> {
                    // Surprise, ...! Transfer window in the middle of the creation flow.
                    activity2.addStartingWindow(mPackageName,
                            android.R.style.Theme, null, "Test", 0, 0, 0, 0,
                            activity1, true, true, false,
                            true, false, false);
                });
        activity1.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();
        assertNoStartingWindow(activity1);
        assertHasStartingWindow(activity2);
    }

    @Test
    public void testTransferStartingWindowCanAnimate() {
        registerTestStartingWindowOrganizer();
        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
        activity1.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();
        activity2.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1,
                true, true, false, true, false, false);
        waitUntilHandlersIdle();
        assertNoStartingWindow(activity1);
        assertHasStartingWindow(activity2);

        // Assert that bottom activity is allowed to do animation.
        ArrayList<WindowContainer> sources = new ArrayList<>();
        sources.add(activity2);
        doReturn(true).when(activity2).okToAnimate();
        doReturn(true).when(activity2).isAnimating();
        assertTrue(activity2.applyAnimation(null, TRANSIT_OLD_ACTIVITY_OPEN, true, false, sources));
    }
    @Test
    public void testTrackingStartingWindowThroughTrampoline() {
        final ActivityRecord sourceRecord = new ActivityBuilder(mAtm)
                .setCreateTask(true).setLaunchedFromUid(Process.SYSTEM_UID).build();
        sourceRecord.showStartingWindow(null /* prev */, true /* newTask */, false,
                true /* startActivity */, null);

        final ActivityRecord secondRecord = new ActivityBuilder(mAtm)
                .setTask(sourceRecord.getTask()).build();
        secondRecord.showStartingWindow(null /* prev */, true /* newTask */, false,
                true /* startActivity */, sourceRecord);
        assertFalse(secondRecord.mSplashScreenStyleEmpty);
        secondRecord.onStartingWindowDrawn();

        final ActivityRecord finalRecord = new ActivityBuilder(mAtm)
                .setTask(sourceRecord.getTask()).build();
        finalRecord.showStartingWindow(null /* prev */, true /* newTask */, false,
                true /* startActivity */, secondRecord);
        assertTrue(finalRecord.mSplashScreenStyleEmpty);
    }

    @Test
    public void testTransferStartingWindowFromFinishingActivity() {
        registerTestStartingWindowOrganizer();
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final Task task = activity.getTask();
        activity.addStartingWindow(mPackageName, android.R.style.Theme, null /* compatInfo */,
                "Test", 0 /* labelRes */, 0 /* icon */, 0 /* logo */, 0 /* windowFlags */,
                null /* transferFrom */, true /* newTask */, true /* taskSwitch */,
                false /* processRunning */, false /* allowTaskSnapshot */,
                false /* activityCreate */, false /* suggestEmpty */);
        waitUntilHandlersIdle();
        assertHasStartingWindow(activity);

        doCallRealMethod().when(task).startActivityLocked(
                any(), any(), anyBoolean(), anyBoolean(), any(), any());
        // In normal case, resumeFocusedTasksTopActivities() should be called after
        // startActivityLocked(). So skip resumeFocusedTasksTopActivities() in ActivityBuilder.
        doReturn(false).when(mRootWindowContainer)
                .resumeFocusedTasksTopActivities();
        // Make mVisibleSetFromTransferredStartingWindow true.
        final ActivityRecord middle = new ActivityBuilder(mAtm).setTask(task).build();
        task.startActivityLocked(middle, null /* focusedTopActivity */,
                false /* newTask */, false /* isTaskSwitch */, null /* options */,
                null /* sourceRecord */);
        middle.makeFinishingLocked();

        assertNull(activity.mStartingWindow);
        assertHasStartingWindow(middle);

        final ActivityRecord top = new ActivityBuilder(mAtm).setTask(task).build();
        // Expect the visibility should be updated to true when transferring starting window from
        // a visible activity.
        top.setVisible(false);
        // The finishing middle should be able to transfer starting window to top.
        task.startActivityLocked(top, null /* focusedTopActivity */,
                false /* newTask */, false /* isTaskSwitch */, null /* options */,
                null /* sourceRecord */);

        assertTrue(mDisplayContent.mSkipAppTransitionAnimation);
        assertNull(middle.mStartingWindow);
        assertHasStartingWindow(top);
        assertTrue(top.isVisible());
        // The activity was visible by mVisibleSetFromTransferredStartingWindow, so after its
        // starting window is transferred, it should restore to invisible.
        assertFalse(middle.isVisible());
    }

    @Test
    public void testTransferStartingWindowSetFixedRotation() {
        registerTestStartingWindowOrganizer();
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final Task task = activity.getTask();
        final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
        topActivity.setVisible(false);
        task.positionChildAt(topActivity, POSITION_TOP);
        activity.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();

        // Make activities to have different rotation from it display and set fixed rotation
        // transform to activity1.
        int rotation = (mDisplayContent.getRotation() + 1) % 4;
        mDisplayContent.setFixedRotationLaunchingApp(activity, rotation);
        doReturn(rotation).when(mDisplayContent)
                .rotationForActivityInDifferentOrientation(topActivity);

        // The transform will be finished because there is no running animation. Keep activity in
        // animating state to avoid the transform being finished.
        doReturn(true).when(activity).isAnimating(anyInt());
        // Make sure the fixed rotation transform linked to activity2 when adding starting window
        // on activity2.
        topActivity.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity,
                false, false, false, true, false, false);
        waitUntilHandlersIdle();
        assertTrue(topActivity.hasFixedRotationTransform());
    }

    @Test
    public void testTryTransferStartingWindowFromHiddenAboveToken() {
        registerTestStartingWindowOrganizer();
        // Add two tasks on top of each other.
        final ActivityRecord activityTop = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final ActivityRecord activityBottom = new ActivityBuilder(mAtm).build();
        activityTop.getTask().addChild(activityBottom, 0);

        // Add a starting window.
        activityTop.addStartingWindow(mPackageName,
                android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
                false, false);
        waitUntilHandlersIdle();

        // Make the top one invisible, and try transferring the starting window from the top to the
        // bottom one.
        activityTop.setVisibility(false, false);
        activityBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
        waitUntilHandlersIdle();

        // Assert that the bottom window now has the starting window.
        assertNoStartingWindow(activityTop);
        assertHasStartingWindow(activityBottom);
    }

    @Test
    public void testStartingWindowInTaskFragment() {
        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final WindowState startingWindow = createWindowState(
                new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING), activity1);
        activity1.addWindow(startingWindow);
        activity1.mStartingData = mock(StartingData.class);
        activity1.attachStartingWindow(startingWindow);
        final Task task = activity1.getTask();
        final Rect taskBounds = task.getBounds();
        final int width = taskBounds.width();
        final int height = taskBounds.height();
        final BiConsumer<TaskFragment, Rect> fragmentSetup = (fragment, bounds) -> {
            final Configuration config = fragment.getRequestedOverrideConfiguration();
            config.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
            config.windowConfiguration.setBounds(bounds);
            fragment.onRequestedOverrideConfigurationChanged(config);
        };

        final TaskFragment taskFragment1 = new TaskFragment(
                mAtm, null /* fragmentToken */, false /* createdByOrganizer */);
        fragmentSetup.accept(taskFragment1, new Rect(0, 0, width / 2, height));
        task.addChild(taskFragment1, POSITION_TOP);

        final TaskFragment taskFragment2 = new TaskFragment(
                mAtm, null /* fragmentToken */, false /* createdByOrganizer */);
        fragmentSetup.accept(taskFragment2, new Rect(width / 2, 0, width, height));
        task.addChild(taskFragment2, POSITION_TOP);
        final ActivityRecord activity2 = new ActivityBuilder(mAtm)
                .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE).build();
        activity2.mVisibleRequested = true;
        taskFragment2.addChild(activity2);
        assertTrue(activity2.isResizeable());
        activity1.reparent(taskFragment1, POSITION_TOP);

        verify(activity1.getSyncTransaction()).reparent(eq(startingWindow.mSurfaceControl),
                eq(task.mSurfaceControl));
        assertEquals(activity1.mStartingData, startingWindow.mStartingData);
        assertEquals(task.mSurfaceControl, startingWindow.getAnimationLeashParent());
        assertEquals(task, activity1.mStartingData.mAssociatedTask);
        assertEquals(taskFragment1.getBounds(), activity1.getBounds());
        // The activity was resized by task fragment, but starting window must still cover the task.
        assertEquals(taskBounds, activity1.mStartingWindow.getBounds());

        // The starting window is only removed when all embedded activities are drawn.
        final WindowState activityWindow = mock(WindowState.class);
        activity1.onFirstWindowDrawn(activityWindow);
        assertNotNull(activity1.mStartingWindow);
        activity2.onFirstWindowDrawn(activityWindow);
        assertNull(activity1.mStartingWindow);
    }

    @Test
    public void testTransitionAnimationBounds() {
        removeGlobalMinSizeRestriction();
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateParentTask(true).setCreateActivity(true).build();
        final Task rootTask = task.getRootTask();
        final ActivityRecord activity = task.getTopNonFinishingActivity();
        final Rect stackBounds = new Rect(0, 0, 1000, 600);
        final Rect taskBounds = new Rect(100, 400, 600, 800);
        // Set the bounds and windowing mode to window configuration directly, otherwise the
        // testing setups may be discarded by configuration resolving.
        rootTask.getWindowConfiguration().setBounds(stackBounds);
        task.getWindowConfiguration().setBounds(taskBounds);
        activity.getWindowConfiguration().setBounds(taskBounds);

        // Check that anim bounds for freeform window match task bounds
        task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM);
        assertEquals(task.getBounds(), activity.getAnimationBounds(ROOT_TASK_CLIP_NONE));

        // ROOT_TASK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
        // bounds animation layer.
        task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        assertEquals(task.getBounds(), activity.getAnimationBounds(ROOT_TASK_CLIP_AFTER_ANIM));

        // Even the activity is smaller than task and it is not aligned to the top-left corner of
        // task, the animation bounds the same as task and position should be zero because in real
        // case the letterbox will fill the remaining area in task.
        final Rect halfBounds = new Rect(taskBounds);
        halfBounds.scale(0.5f);
        activity.getWindowConfiguration().setBounds(halfBounds);
        final Point animationPosition = new Point();
        activity.getAnimationPosition(animationPosition);

        assertEquals(taskBounds, activity.getAnimationBounds(ROOT_TASK_CLIP_AFTER_ANIM));
        assertEquals(new Point(0, 0), animationPosition);
    }

    @Test
    public void testTransitionAnimationBounds_returnTaskFragment() {
        removeGlobalMinSizeRestriction();
        final Task task = new TaskBuilder(mSupervisor).setCreateParentTask(true).build();
        final Task rootTask = task.getRootTask();
        final TaskFragment taskFragment = createTaskFragmentWithParentTask(task,
                false /* createEmbeddedTask */);
        final ActivityRecord activity = taskFragment.getTopNonFinishingActivity();
        final Rect stackBounds = new Rect(0, 0, 1000, 600);
        final Rect taskBounds = new Rect(100, 400, 600, 800);
        final Rect taskFragmentBounds = new Rect(100, 400, 300, 800);
        final Rect activityBounds = new Rect(100, 400, 300, 600);
        // Set the bounds and windowing mode to window configuration directly, otherwise the
        // testing setups may be discarded by configuration resolving.
        rootTask.getWindowConfiguration().setBounds(stackBounds);
        task.getWindowConfiguration().setBounds(taskBounds);
        taskFragment.getWindowConfiguration().setBounds(taskFragmentBounds);
        activity.getWindowConfiguration().setBounds(activityBounds);

        // Check that anim bounds for freeform window match task fragment bounds
        task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FREEFORM);
        assertEquals(taskFragment.getBounds(), activity.getAnimationBounds(ROOT_TASK_CLIP_NONE));

        // ROOT_TASK_CLIP_AFTER_ANIM should use task fragment bounds since they will be clipped by
        // bounds animation layer.
        task.getWindowConfiguration().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        assertEquals(taskFragment.getBounds(),
                activity.getAnimationBounds(ROOT_TASK_CLIP_AFTER_ANIM));
    }

    @Test
    public void testHasStartingWindow() {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
        final WindowManager.LayoutParams attrs =
                new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
        final TestWindowState startingWindow = createWindowState(attrs, activity);
        activity.startingDisplayed = true;
        activity.addWindow(startingWindow);
        assertTrue("Starting window should be present", activity.hasStartingWindow());
        activity.startingDisplayed = false;
        assertTrue("Starting window should be present", activity.hasStartingWindow());

        activity.removeChild(startingWindow);
        assertFalse("Starting window should not be present", activity.hasStartingWindow());
    }

    @Test
    public void testCloseToSquareFixedOrientationPortrait() {
        // create a square display
        final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000)
                .setSystemDecorations(true).build();
        final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build();

        // create a fixed portrait activity
        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task)
                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT).build();

        // check that both the configuration and app bounds are portrait
        assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);
        assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width()
                <= activity.getConfiguration().windowConfiguration.getAppBounds().height());
    }

    @Test
    public void testCloseToSquareFixedOrientationLandscape() {
        // create a square display
        final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000)
                .setSystemDecorations(true).build();
        final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build();

        // create a fixed landscape activity
        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task)
                .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE).build();

        // check that both the configuration and app bounds are landscape
        assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation);
        assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width()
                > activity.getConfiguration().windowConfiguration.getAppBounds().height());
    }

    @Test
    public void testSetVisibility_visibleToVisible() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true).build();
        // By default, activity is visible.
        assertTrue(activity.isVisible());
        assertTrue(activity.mVisibleRequested);
        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));

        // Request the activity to be visible. Although the activity is already visible, app
        // transition animation should be applied on this activity. This might be unnecessary, but
        // until we verify no logic relies on this behavior, we'll keep this as is.
        activity.setVisibility(true);
        assertTrue(activity.isVisible());
        assertTrue(activity.mVisibleRequested);
        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
    }

    @Test
    public void testSetVisibility_visibleToInvisible() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true).build();
        // By default, activity is visible.
        assertTrue(activity.isVisible());
        assertTrue(activity.mVisibleRequested);
        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));

        // Request the activity to be invisible. Since the visibility changes, app transition
        // animation should be applied on this activity.
        activity.setVisibility(false);
        assertTrue(activity.isVisible());
        assertFalse(activity.mVisibleRequested);
        assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertTrue(activity.mDisplayContent.mClosingApps.contains(activity));
    }

    @Test
    public void testSetVisibility_invisibleToVisible() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true).setVisible(false).build();
        // Activiby is invisible. However ATMS requests it to become visible, since this is a top
        // activity.
        assertFalse(activity.isVisible());
        assertTrue(activity.mVisibleRequested);
        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));

        // Request the activity to be visible. Since the visibility changes, app transition
        // animation should be applied on this activity.
        activity.setVisibility(true);
        assertFalse(activity.isVisible());
        assertTrue(activity.mVisibleRequested);
        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
    }

    @Test
    public void testSetVisibility_invisibleToInvisible() {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setCreateTask(true).setVisible(false).build();
        // Activiby is invisible. However ATMS requests it to become visible, since this is a top
        // activity.
        assertFalse(activity.isVisible());
        assertTrue(activity.mVisibleRequested);
        assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));

        // Request the activity to be invisible. Since the activity is already invisible, no app
        // transition should be applied on this activity.
        activity.setVisibility(false);
        assertFalse(activity.isVisible());
        assertFalse(activity.mVisibleRequested);
        assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
    }

    @Test
    public void testImeInsetsFrozenFlag_resetWhenReparented() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowState app = createWindow(null, TYPE_APPLICATION, activity, "app");
        final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
        final Task newTask = new TaskBuilder(mSupervisor).build();
        makeWindowVisible(app, imeWindow);
        mDisplayContent.mInputMethodWindow = imeWindow;
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);

        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
        app.mActivityRecord.commitVisibility(false, false);
        assertTrue(app.mActivityRecord.mLastImeShown);
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Expect IME insets frozen state will reset when the activity is reparent to the new task.
        activity.setState(RESUMED, "test");
        activity.reparent(newTask, 0 /* top */, "test");
        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenResized() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        makeWindowVisibleAndDrawn(app, mImeWindow);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);

        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
        app.mActivityRecord.commitVisibility(false, false);
        assertTrue(app.mActivityRecord.mLastImeShown);
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Expect IME insets frozen state will reset when the activity is reparent to the new task.
        app.mActivityRecord.onResize();
        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        makeWindowVisibleAndDrawn(app, mImeWindow);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);

        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
        mDisplayContent.mOpeningApps.clear();
        app.mActivityRecord.commitVisibility(false, false);
        app.mActivityRecord.onWindowsGone();

        assertTrue(app.mActivityRecord.mLastImeShown);
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Expect IME insets frozen state will reset when the activity has no IME focusable window.
        app.mActivityRecord.forAllWindowsUnchecked(w -> {
            w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
            return true;
        }, true);

        app.mActivityRecord.commitVisibility(true, false);
        app.mActivityRecord.onWindowsVisible();

        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");

        InsetsSource imeSource = new InsetsSource(ITYPE_IME);
        app.getInsetsState().addSource(imeSource);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.updateImeInputAndControlTarget(app);

        InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
        assertFalse(state.getSource(ITYPE_IME).isVisible());
        assertTrue(state.getSource(ITYPE_IME).getFrame().isEmpty());

        // Simulate app is closing and expect IME insets is frozen.
        mDisplayContent.mOpeningApps.clear();
        app.mActivityRecord.commitVisibility(false, false);
        app.mActivityRecord.onWindowsGone();
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Simulate app re-start input or turning screen off/on then unlocked by un-secure
        // keyguard to back to the app, expect IME insets is not frozen
        mDisplayContent.updateImeInputAndControlTarget(app);
        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
        imeSource.setFrame(new Rect(100, 400, 500, 500));
        app.getInsetsState().addSource(imeSource);
        app.getInsetsState().setSourceVisible(ITYPE_IME, true);

        // Verify when IME is visible and the app can receive the right IME insets from policy.
        makeWindowVisibleAndDrawn(app, mImeWindow);
        state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
        assertTrue(state.getSource(ITYPE_IME).isVisible());
        assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
    }

    @UseTestDisplay(addWindows = {W_ACTIVITY, W_INPUT_METHOD})
    @Test
    public void testImeInsetsFrozenFlag_noDispatchVisibleInsetsWhenAppNotRequest()
            throws RemoteException {
        final WindowState app1 = createWindow(null, TYPE_APPLICATION, "app1");
        final WindowState app2 = createWindow(null, TYPE_APPLICATION, "app2");

        mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_IME).setWindow(
                mImeWindow, null, null);
        mImeWindow.getControllableInsetProvider().setServerVisible(true);

        // Simulate app2 is closing and let app1 is visible to be IME targets.
        makeWindowVisibleAndDrawn(app1, mImeWindow);
        mDisplayContent.setImeLayeringTarget(app1);
        mDisplayContent.updateImeInputAndControlTarget(app1);
        app2.mActivityRecord.commitVisibility(false, false);

        // app1 requests IME visible.
        final InsetsVisibilities requestedVisibilities = new InsetsVisibilities();
        requestedVisibilities.setVisibility(ITYPE_IME, true);
        app1.setRequestedVisibilities(requestedVisibilities);
        mDisplayContent.getInsetsStateController().onInsetsModified(app1);

        // Verify app1's IME insets is visible and app2's IME insets frozen flag set.
        assertTrue(app1.getInsetsState().peekSource(ITYPE_IME).isVisible());
        assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Simulate switching to app2 to make it visible to be IME targets.
        makeWindowVisibleAndDrawn(app2);
        spyOn(app2);
        spyOn(app2.mClient);
        ArgumentCaptor<InsetsState> insetsStateCaptor = ArgumentCaptor.forClass(InsetsState.class);
        doReturn(true).when(app2).isReadyToDispatchInsetsState();
        mDisplayContent.setImeLayeringTarget(app2);
        mDisplayContent.updateImeInputAndControlTarget(app2);

        // Verify after unfreezing app2's IME insets state, we won't dispatch visible IME insets
        // to client if the app didn't request IME visible.
        assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);
        verify(app2.mClient, atLeastOnce()).insetsChanged(insetsStateCaptor.capture(), anyBoolean(),
                anyBoolean());
        assertFalse(insetsStateCaptor.getAllValues().get(0).peekSource(ITYPE_IME).isVisible());
    }

    @Test
    public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        makeWindowVisibleAndDrawn(app);

        // Put the activity in close transition.
        mDisplayContent.mOpeningApps.clear();
        mDisplayContent.mClosingApps.add(app.mActivityRecord);
        mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);

        // Remove window during transition, so it is requested to hide, but won't be committed until
        // the transition is finished.
        app.mActivityRecord.onRemovedFromDisplay();

        assertTrue(mDisplayContent.mClosingApps.contains(app.mActivityRecord));
        assertFalse(app.mActivityRecord.isVisibleRequested());
        assertTrue(app.mActivityRecord.isVisible());
        assertTrue(app.mActivityRecord.isSurfaceShowing());

        // Start transition.
        app.mActivityRecord.prepareSurfaces();

        // Because the app is waiting for transition, it should not hide the surface.
        assertTrue(app.mActivityRecord.isSurfaceShowing());
    }

    @Test
    public void testInClosingAnimation_visibilityCommitted_hideSurface() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        makeWindowVisibleAndDrawn(app);

        // Put the activity in close transition.
        mDisplayContent.mOpeningApps.clear();
        mDisplayContent.mClosingApps.add(app.mActivityRecord);
        mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);

        // Commit visibility before start transition.
        app.mActivityRecord.commitVisibility(false, false);

        assertFalse(app.mActivityRecord.isVisibleRequested());
        assertFalse(app.mActivityRecord.isVisible());
        assertTrue(app.mActivityRecord.isSurfaceShowing());

        // Start transition.
        app.mActivityRecord.prepareSurfaces();

        // Because the app visibility has been committed before the transition start, it should hide
        // the surface.
        assertFalse(app.mActivityRecord.isSurfaceShowing());
    }

    private void assertHasStartingWindow(ActivityRecord atoken) {
        assertNotNull(atoken.mStartingSurface);
        assertNotNull(atoken.mStartingData);
        assertNotNull(atoken.mStartingWindow);
    }

    private void assertNoStartingWindow(ActivityRecord atoken) {
        assertNull(atoken.mStartingSurface);
        assertNull(atoken.mStartingWindow);
        assertNull(atoken.mStartingData);
        atoken.forAllWindows(windowState -> {
            assertFalse(windowState.getBaseType() == TYPE_APPLICATION_STARTING);
        }, true);
    }
}
