/*
 * Copyright (C) 2016 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 android.server.cts;

import static android.server.cts.ActivityManagerState.RESIZE_MODE_RESIZEABLE;
import static android.server.cts.ActivityManagerTestBase.DOCKED_STACK_ID;
import static android.server.cts.ActivityManagerTestBase.FREEFORM_WORKSPACE_STACK_ID;
import static android.server.cts.ActivityManagerTestBase.HOME_STACK_ID;
import static android.server.cts.ActivityManagerTestBase.PINNED_STACK_ID;
import static android.server.cts.ActivityManagerTestBase.componentName;
import static android.server.cts.StateLogger.log;

import android.server.cts.ActivityManagerState.ActivityStack;
import android.server.cts.ActivityManagerState.ActivityTask;
import android.server.cts.WindowManagerState.WindowStack;
import android.server.cts.WindowManagerState.WindowState;
import android.server.cts.WindowManagerState.WindowTask;

import com.android.tradefed.device.ITestDevice;

import junit.framework.Assert;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Predicate;

/** Combined state of the activity manager and window manager. */
public class ActivityAndWindowManagersState extends Assert {

    // Clone of android DisplayMetrics.DENSITY_DEFAULT (DENSITY_MEDIUM)
    // (Needed in host-side tests to convert dp to px.)
    private static final int DISPLAY_DENSITY_DEFAULT = 160;
    public static final int DEFAULT_DISPLAY_ID = 0;

    // Default minimal size of resizable task, used if none is set explicitly.
    // Must be kept in sync with 'default_minimal_size_resizable_task' dimen from frameworks/base.
    private static final int DEFAULT_RESIZABLE_TASK_SIZE_DP = 220;

    // Default minimal size of a resizable PiP task, used if none is set explicitly.
    // Must be kept in sync with 'default_minimal_size_pip_resizable_task' dimen from
    // frameworks/base.
    private static final int DEFAULT_PIP_RESIZABLE_TASK_SIZE_DP = 108;

    private ActivityManagerState mAmState = new ActivityManagerState();
    private WindowManagerState mWmState = new WindowManagerState();

    private final List<WindowManagerState.WindowState> mTempWindowList = new ArrayList<>();

    private boolean mUseActivityNames = true;

    /**
     * Compute AM and WM state of device, check sanity and bounds.
     * WM state will include only visible windows, stack and task bounds will be compared.
     *
     * @param device test device.
     * @param waitForActivitiesVisible array of activity names to wait for.
     */
    public void computeState(ITestDevice device, String[] waitForActivitiesVisible)
            throws Exception {
        computeState(device, waitForActivitiesVisible, true);
    }

    /**
     * Compute AM and WM state of device, check sanity and bounds.
     *
     * @param device test device.
     * @param waitForActivitiesVisible array of activity names to wait for.
     * @param compareTaskAndStackBounds pass 'true' if stack and task bounds should be compared,
     *                                  'false' otherwise.
     */
    void computeState(ITestDevice device, String[] waitForActivitiesVisible,
                      boolean compareTaskAndStackBounds) throws Exception {
        waitForValidState(device, waitForActivitiesVisible, null /* stackIds */,
                compareTaskAndStackBounds);

        assertSanity();
        assertValidBounds(compareTaskAndStackBounds);
    }

    /**
     * By default computeState allows you to pass only the activity name it and
     * it will generate the full window name for the main activity window. In the
     * case of secondary application windows though this isn't helpful, as they
     * may follow a different format, so this method lets you disable that behavior,
     * prior to calling a computeState variant
     */
    void setUseActivityNamesForWindowNames(boolean useActivityNames) {
        mUseActivityNames = useActivityNames;
    }

    /**
     * Compute AM and WM state of device, wait for the activity records to be added, and
     * wait for debugger window to show up.
     *
     * This should only be used when starting with -D (debugger) option, where we pop up the
     * waiting-for-debugger window, but real activity window won't show up since we're waiting
     * for debugger.
     */
    void waitForDebuggerWindowVisible(
            ITestDevice device, String[] waitForActivityRecords) throws Exception {
        int retriesLeft = 5;
        do {
            mAmState.computeState(device);
            mWmState.computeState(device);
            if (shouldWaitForDebuggerWindow() ||
                    shouldWaitForActivityRecords(waitForActivityRecords)) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log(e.toString());
                    // Well I guess we are not waiting...
                }
            } else {
                break;
            }
        } while (retriesLeft-- > 0);
    }

    /**
     * Wait for the activity to appear and for valid state in AM and WM.
     *
     * @param device test device.
     * @param waitForActivityVisible name of activity to wait for.
     */
    void waitForValidState(ITestDevice device, String waitForActivityVisible)
            throws Exception {
        waitForValidState(device, new String[]{waitForActivityVisible}, null /* stackIds */,
                false /* compareTaskAndStackBounds */);
    }

    /**
     * Wait for the activity to appear in proper stack and for valid state in AM and WM.
     *
     * @param device test device.
     * @param waitForActivityVisible name of activity to wait for.
     * @param stackId id of the stack where provided activity should be found.
     */
    void waitForValidState(ITestDevice device, String waitForActivityVisible, int stackId)
            throws Exception {
        waitForValidState(device, new String[]{waitForActivityVisible}, new int[]{stackId},
                false /* compareTaskAndStackBounds */);
    }

    /**
     * Wait for the activities to appear in proper stacks and for valid state in AM and WM.
     *
     * @param device test device.
     * @param waitForActivitiesVisible array of activity names to wait for.
     * @param stackIds ids of stack where provided activities should be found.
     *                 Pass null to skip this check.
     * @param compareTaskAndStackBounds flag indicating if we should compare task and stack bounds
     *                                  for equality.
     */
    void waitForValidState(ITestDevice device, String[] waitForActivitiesVisible, int[] stackIds,
            boolean compareTaskAndStackBounds) throws Exception {
        waitForValidState(device, waitForActivitiesVisible, stackIds, compareTaskAndStackBounds,
                componentName);
    }

    /**
     * Wait for the activities to appear in proper stacks and for valid state in AM and WM.
     *
     * @param device test device.
     * @param waitForActivitiesVisible array of activity names to wait for.
     * @param stackIds ids of stack where provided activities should be found.
     *                 Pass null to skip this check.
     * @param compareTaskAndStackBounds flag indicating if we should compare task and stack bounds
     *                                  for equality.
     * @param packageName name of the package of activities that we're waiting for.
     */
    void waitForValidState(ITestDevice device, String[] waitForActivitiesVisible, int[] stackIds,
            boolean compareTaskAndStackBounds, String packageName) throws Exception {
        int retriesLeft = 5;
        do {
            // TODO: Get state of AM and WM at the same time to avoid mismatches caused by
            // requesting dump in some intermediate state.
            mAmState.computeState(device);
            mWmState.computeState(device);
            if (shouldWaitForValidStacks(compareTaskAndStackBounds)
                    || shouldWaitForActivities(waitForActivitiesVisible, stackIds, packageName)
                    || shouldWaitForWindows()) {
                log("***Waiting for valid stacks and activities states...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log(e.toString());
                    // Well I guess we are not waiting...
                }
            } else {
                break;
            }
        } while (retriesLeft-- > 0);
    }

    void waitForHomeActivityVisible(ITestDevice device) throws Exception {
        waitForWithAmState(device, ActivityManagerState::isHomeActivityVisible,
                "***Waiting for home activity to be visible...");
    }

    void waitForKeyguardShowingAndNotOccluded(ITestDevice device) throws Exception {
        waitForWithAmState(device, state -> state.getKeyguardControllerState().keyguardShowing
                        && !state.getKeyguardControllerState().keyguardOccluded,
                "***Waiting for Keyguard showing...");
    }

    void waitForKeyguardShowingAndOccluded(ITestDevice device) throws Exception {
        waitForWithAmState(device, state -> state.getKeyguardControllerState().keyguardShowing
                        && state.getKeyguardControllerState().keyguardOccluded,
                "***Waiting for Keyguard showing and occluded...");
    }

    void waitForKeyguardGone(ITestDevice device) throws Exception {
        waitForWithAmState(device, state -> !state.getKeyguardControllerState().keyguardShowing,
                "***Waiting for Keyguard gone...");
    }

    void waitForRotation(ITestDevice device, int rotation) throws Exception {
        waitForWithWmState(device, state -> state.getRotation() == rotation,
                "***Waiting for Rotation: " + rotation);
    }

    void waitForDisplayUnfrozen(ITestDevice device) throws Exception {
        waitForWithWmState(device, state -> !state.isDisplayFrozen(),
                "***Waiting for Display unfrozen");
    }

    void waitForActivityState(ITestDevice device, String activityName, String activityState)
            throws Exception {
        waitForWithAmState(device, state -> state.hasActivityState(activityName, activityState),
                "***Waiting for Activity State: " + activityState);
    }

    void waitForFocusedStack(ITestDevice device, int stackId) throws Exception {
        waitForWithAmState(device, state -> state.getFocusedStackId() == stackId,
                "***Waiting for focused stack...");
    }

    void waitForAppTransitionIdle(ITestDevice device) throws Exception {
        waitForWithWmState(device,
                state -> WindowManagerState.APP_STATE_IDLE.equals(state.getAppTransitionState()),
                "***Waiting for app transition idle...");
    }

    void waitForWithAmState(ITestDevice device, Predicate<ActivityManagerState> waitCondition,
            String message) throws Exception{
        waitFor(device, (amState, wmState) -> waitCondition.test(amState), message);
    }

    void waitForWithWmState(ITestDevice device, Predicate<WindowManagerState> waitCondition,
            String message) throws Exception{
        waitFor(device, (amState, wmState) -> waitCondition.test(wmState), message);
    }

    void waitFor(ITestDevice device,
            BiPredicate<ActivityManagerState, WindowManagerState> waitCondition, String message)
            throws Exception {
        int retriesLeft = 5;
        do {
            mAmState.computeState(device);
            mWmState.computeState(device);
            if (!waitCondition.test(mAmState, mWmState)) {
                log(message);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log(e.toString());
                    // Well I guess we are not waiting...
                }
            } else {
                break;
            }
        } while (retriesLeft-- > 0);
    }

    /** @return true if should wait for valid stacks state. */
    private boolean shouldWaitForValidStacks(boolean compareTaskAndStackBounds) {
        if (!taskListsInAmAndWmAreEqual()) {
            // We want to wait for equal task lists in AM and WM in case we caught them in the
            // middle of some state change operations.
            log("***taskListsInAmAndWmAreEqual=false");
            return true;
        }
        if (!stackBoundsInAMAndWMAreEqual()) {
            // We want to wait a little for the stacks in AM and WM to have equal bounds as there
            // might be a transition animation ongoing when we got the states from WM AM separately.
            log("***stackBoundsInAMAndWMAreEqual=false");
            return true;
        }
        try {
            // Temporary fix to avoid catching intermediate state with different task bounds in AM
            // and WM.
            assertValidBounds(compareTaskAndStackBounds);
        } catch (AssertionError e) {
            log("***taskBoundsInAMAndWMAreEqual=false : " + e.getMessage());
            return true;
        }
        final int stackCount = mAmState.getStackCount();
        if (stackCount == 0) {
            log("***stackCount=" + stackCount);
            return true;
        }
        final int resumedActivitiesCount = mAmState.getResumedActivitiesCount();
        if (!mAmState.getKeyguardControllerState().keyguardShowing && resumedActivitiesCount != 1) {
            log("***resumedActivitiesCount=" + resumedActivitiesCount);
            return true;
        }
        if (mAmState.getFocusedActivity() == null) {
            log("***focusedActivity=null");
            return true;
        }
        return false;
    }

    /** @return true if should wait for some activities to become visible. */
    private boolean shouldWaitForActivities(String[] waitForActivitiesVisible, int[] stackIds,
            String packageName) {
        if (waitForActivitiesVisible == null || waitForActivitiesVisible.length == 0) {
            return false;
        }
        // If the caller is interested in us waiting for some particular activity windows to be
        // visible before compute the state. Check for the visibility of those activity windows
        // and for placing them in correct stacks (if requested).
        boolean allActivityWindowsVisible = true;
        boolean tasksInCorrectStacks = true;
        List<WindowManagerState.WindowState> matchingWindowStates = new ArrayList<>();
        for (int i = 0; i < waitForActivitiesVisible.length; i++) {
            // Check if window is visible - it should be represented as one of the window states.
            final String windowName = mUseActivityNames ?
                    ActivityManagerTestBase.getWindowName(packageName, waitForActivitiesVisible[i])
                    : waitForActivitiesVisible[i];
            final String activityComponentName =
                    ActivityManagerTestBase.getActivityComponentName(packageName,
                            waitForActivitiesVisible[i]);

            mWmState.getMatchingVisibleWindowState(windowName, matchingWindowStates);
            boolean activityWindowVisible = !matchingWindowStates.isEmpty();
            if (!activityWindowVisible) {
                log("Activity window not visible: " + windowName);
                allActivityWindowsVisible = false;
            } else if (!mAmState.isActivityVisible(activityComponentName)) {
                log("Activity not visible: " + activityComponentName);
                allActivityWindowsVisible = false;
            } else if (stackIds != null) {
                // Check if window is already in stack requested by test.
                boolean windowInCorrectStack = false;
                for (WindowManagerState.WindowState ws : matchingWindowStates) {
                    if (ws.getStackId() == stackIds[i]) {
                        windowInCorrectStack = true;
                        break;
                    }
                }
                if (!windowInCorrectStack) {
                    log("Window in incorrect stack: " + waitForActivitiesVisible[i]);
                    tasksInCorrectStacks = false;
                }
            }
        }
        return !allActivityWindowsVisible || !tasksInCorrectStacks;
    }

    /** @return true if should wait valid windows state. */
    private boolean shouldWaitForWindows() {
        if (mWmState.getFrontWindow() == null) {
            log("***frontWindow=null");
            return true;
        }
        if (mWmState.getFocusedWindow() == null) {
            log("***focusedWindow=null");
            return true;
        }
        if (mWmState.getFocusedApp() == null) {
            log("***focusedApp=null");
            return true;
        }

        return false;
    }

    private boolean shouldWaitForDebuggerWindow() {
        List<WindowManagerState.WindowState> matchingWindowStates = new ArrayList<>();
        mWmState.getMatchingVisibleWindowState("android.server.cts", matchingWindowStates);
        for (WindowState ws : matchingWindowStates) {
            if (ws.isDebuggerWindow()) {
                return false;
            }
        }
        log("Debugger window not available yet");
        return true;
    }

    private boolean shouldWaitForActivityRecords(String[] waitForActivityRecords) {
        if (waitForActivityRecords == null || waitForActivityRecords.length == 0) {
            return false;
        }
        // Check if the activity records we're looking for is already added.
        for (int i = 0; i < waitForActivityRecords.length; i++) {
            if (!mAmState.isActivityVisible(waitForActivityRecords[i])) {
                log("ActivityRecord " + waitForActivityRecords[i] + " not visible yet");
                return true;
            }
        }
        return false;
    }

    ActivityManagerState getAmState() {
        return mAmState;
    }

    public WindowManagerState getWmState() {
        return mWmState;
    }

    void assertSanity() throws Exception {
        assertTrue("Must have stacks", mAmState.getStackCount() > 0);
        if (!mAmState.getKeyguardControllerState().keyguardShowing) {
            assertEquals("There should be one and only one resumed activity in the system.",
                    1, mAmState.getResumedActivitiesCount());
        }
        assertNotNull("Must have focus activity.", mAmState.getFocusedActivity());

        for (ActivityStack aStack : mAmState.getStacks()) {
            final int stackId = aStack.mStackId;
            for (ActivityTask aTask : aStack.getTasks()) {
                assertEquals("Stack can only contain its own tasks", stackId, aTask.mStackId);
            }
        }

        assertNotNull("Must have front window.", mWmState.getFrontWindow());
        assertNotNull("Must have focused window.", mWmState.getFocusedWindow());
        assertNotNull("Must have app.", mWmState.getFocusedApp());
    }

    void assertContainsStack(String msg, int stackId) throws Exception {
        assertTrue(msg, mAmState.containsStack(stackId));
        assertTrue(msg, mWmState.containsStack(stackId));
    }

    void assertDoesNotContainStack(String msg, int stackId) throws Exception {
        assertFalse(msg, mAmState.containsStack(stackId));
        assertFalse(msg, mWmState.containsStack(stackId));
    }

    void assertFrontStack(String msg, int stackId) throws Exception {
        assertEquals(msg, stackId, mAmState.getFrontStackId(DEFAULT_DISPLAY_ID));
        assertEquals(msg, stackId, mWmState.getFrontStackId(DEFAULT_DISPLAY_ID));
    }

    void assertFocusedStack(String msg, int stackId) throws Exception {
        assertEquals(msg, stackId, mAmState.getFocusedStackId());
    }

    void assertNotFocusedStack(String msg, int stackId) throws Exception {
        if (stackId == mAmState.getFocusedStackId()) {
            failNotEquals(msg, stackId, mAmState.getFocusedStackId());
        }
    }

    void assertFocusedActivity(String msg, String activityName) throws Exception {
        assertFocusedActivity(msg, componentName, activityName);
    }

    void assertFocusedActivity(String msg, String packageName, String activityName)
            throws Exception {
        final String componentName = ActivityManagerTestBase.getActivityComponentName(packageName,
                activityName);
        assertEquals(msg, componentName, mAmState.getFocusedActivity());
        assertEquals(msg, componentName, mWmState.getFocusedApp());
    }

    void assertNotFocusedActivity(String msg, String activityName) throws Exception {
        final String componentName = ActivityManagerTestBase.getActivityComponentName(activityName);
        if (mAmState.getFocusedActivity().equals(componentName)) {
            failNotEquals(msg, mAmState.getFocusedActivity(), componentName);
        }
        if (mWmState.getFocusedApp().equals(componentName)) {
            failNotEquals(msg, mWmState.getFocusedApp(), componentName);
        }
    }

    void assertResumedActivity(String msg, String activityName) throws Exception {
        final String componentName = ActivityManagerTestBase.getActivityComponentName(activityName);
        assertEquals(msg, componentName, mAmState.getResumedActivity());
    }

    void assertNotResumedActivity(String msg, String activityName) throws Exception {
        final String componentName = ActivityManagerTestBase.getActivityComponentName(activityName);
        if (mAmState.getResumedActivity().equals(componentName)) {
            failNotEquals(msg, mAmState.getResumedActivity(), componentName);
        }
    }

    void assertFocusedWindow(String msg, String windowName) {
        assertEquals(msg, windowName, mWmState.getFocusedWindow());
    }

    void assertNotFocusedWindow(String msg, String windowName) {
        if (mWmState.getFocusedWindow().equals(windowName)) {
            failNotEquals(msg, mWmState.getFocusedWindow(), windowName);
        }
    }

    void assertFrontWindow(String msg, String windowName) {
        assertEquals(msg, windowName, mWmState.getFrontWindow());
    }

    void assertVisibility(String activityName, boolean visible) {
        final String activityComponentName =
                ActivityManagerTestBase.getActivityComponentName(activityName);
        final String windowName =
                ActivityManagerTestBase.getWindowName(activityName);
        assertVisibility(activityComponentName, windowName, visible);
    }

    private void assertVisibility(String activityComponentName, String windowName,
            boolean visible) {
        final boolean activityVisible = mAmState.isActivityVisible(activityComponentName);
        final boolean windowVisible = mWmState.isWindowVisible(windowName);

        if (visible) {
            assertTrue("Activity=" + activityComponentName + " must be visible.", activityVisible);
            assertTrue("Window=" + windowName + " must be visible.", windowVisible);
        } else {
            assertFalse("Activity=" + activityComponentName + " must NOT be visible.",
                    activityVisible);
            assertFalse("Window=" + windowName + " must NOT be visible.", windowVisible);
        }
    }

    void assertHomeActivityVisible(boolean visible) {
        String name = mAmState.getHomeActivityName();
        assertNotNull(name);
        assertVisibility(name, getWindowNameForActivityName(name), visible);
    }

    private String getWindowNameForActivityName(String activityName) {
        return activityName.replaceAll("(.*)\\/\\.", "$1/$1.");
    }

    boolean taskListsInAmAndWmAreEqual() {
        for (ActivityStack aStack : mAmState.getStacks()) {
            final int stackId = aStack.mStackId;
            final WindowStack wStack = mWmState.getStack(stackId);
            if (wStack == null) {
                log("Waiting for stack setup in WM, stackId=" + stackId);
                return false;
            }

            for (ActivityTask aTask : aStack.getTasks()) {
                if (wStack.getTask(aTask.mTaskId) == null) {
                    log("Task is in AM but not in WM, waiting for it to settle, taskId="
                            + aTask.mTaskId);
                    return false;
                }
            }

            for (WindowTask wTask : wStack.mTasks) {
                if (aStack.getTask(wTask.mTaskId) == null) {
                    log("Task is in WM but not in AM, waiting for it to settle, taskId="
                            + wTask.mTaskId);
                    return false;
                }
            }
        }
        return true;
    }

    int getStackPosition(int stackId) {
        int wmStackIndex = mWmState.getStackPosition(stackId);
        int amStackIndex = mAmState.getStackPosition(stackId);
        assertEquals("Window and activity manager must have the same stack position index",
                amStackIndex, wmStackIndex);
        return wmStackIndex;
    }

    boolean stackBoundsInAMAndWMAreEqual() {
        for (ActivityStack aStack : mAmState.getStacks()) {
            final int stackId = aStack.mStackId;
            final WindowStack wStack = mWmState.getStack(stackId);
            if (aStack.isFullscreen() != wStack.isFullscreen()) {
                log("Waiting for correct fullscreen state, stackId=" + stackId);
                return false;
            }

            final Rectangle aStackBounds = aStack.getBounds();
            final Rectangle wStackBounds = wStack.getBounds();

            if (aStack.isFullscreen()) {
                if (aStackBounds != null) {
                    log("Waiting for correct stack state in AM, stackId=" + stackId);
                    return false;
                }
            } else if (!Objects.equals(aStackBounds, wStackBounds)) {
                // If stack is not fullscreen - comparing bounds. Not doing it always because
                // for fullscreen stack bounds in WM can be either null or equal to display size.
                log("Waiting for stack bound equality in AM and WM, stackId=" + stackId);
                return false;
            }
        }

        return true;
    }

    /** Check task bounds when docked to top/left. */
    void assertDockedTaskBounds(int taskWidth, int taskHeight, String activityName) {
        // Task size can be affected by default minimal size.
        int defaultMinimalTaskSize = defaultMinimalTaskSize(
                mAmState.getStackById(ActivityManagerTestBase.DOCKED_STACK_ID).mDisplayId);
        int targetWidth = Math.max(taskWidth, defaultMinimalTaskSize);
        int targetHeight = Math.max(taskHeight, defaultMinimalTaskSize);

        assertEquals(new Rectangle(0, 0, targetWidth, targetHeight),
                mAmState.getTaskByActivityName(activityName).getBounds());
    }

    void assertValidBounds(boolean compareTaskAndStackBounds) {
        // Cycle through the stacks and tasks to figure out if the home stack is resizable
        final ActivityTask homeTask = mAmState.getHomeTask();
        final boolean homeStackIsResizable = homeTask != null
                && homeTask.getResizeMode().equals(RESIZE_MODE_RESIZEABLE);

        for (ActivityStack aStack : mAmState.getStacks()) {
            final int stackId = aStack.mStackId;
            final WindowStack wStack = mWmState.getStack(stackId);
            assertNotNull("stackId=" + stackId + " in AM but not in WM?", wStack);

            assertEquals("Stack fullscreen state in AM and WM must be equal stackId=" + stackId,
                    aStack.isFullscreen(), wStack.isFullscreen());

            final Rectangle aStackBounds = aStack.getBounds();
            final Rectangle wStackBounds = wStack.getBounds();

            if (aStack.isFullscreen()) {
                assertNull("Stack bounds in AM must be null stackId=" + stackId, aStackBounds);
            } else {
                assertEquals("Stack bounds in AM and WM must be equal stackId=" + stackId,
                        aStackBounds, wStackBounds);
            }

            for (ActivityTask aTask : aStack.getTasks()) {
                final int taskId = aTask.mTaskId;
                final WindowTask wTask = wStack.getTask(taskId);
                assertNotNull(
                        "taskId=" + taskId + " in AM but not in WM? stackId=" + stackId, wTask);

                final boolean aTaskIsFullscreen = aTask.isFullscreen();
                final boolean wTaskIsFullscreen = wTask.isFullscreen();
                assertEquals("Task fullscreen state in AM and WM must be equal taskId=" + taskId
                        + ", stackId=" + stackId, aTaskIsFullscreen, wTaskIsFullscreen);

                final Rectangle aTaskBounds = aTask.getBounds();
                final Rectangle wTaskBounds = wTask.getBounds();
                final Rectangle displayRect = mWmState.getDisplay(aStack.mDisplayId)
                        .getDisplayRect();

                if (aTaskIsFullscreen) {
                    assertNull("Task bounds in AM must be null for fullscreen taskId=" + taskId,
                            aTaskBounds);
                } else if (!homeStackIsResizable && mWmState.isDockedStackMinimized()
                        && displayRect.getWidth() > displayRect.getHeight()) {
                    // When minimized using non-resizable launcher in landscape mode, it will move
                    // the task offscreen in the negative x direction unlike portrait that crops.
                    // The x value in the task bounds will not match the stack bounds since the
                    // only the task was moved.
                    assertEquals("Task bounds in AM and WM must match width taskId=" + taskId
                            + ", stackId" + stackId, aTaskBounds.getWidth(),
                            wTaskBounds.getWidth());
                    assertEquals("Task bounds in AM and WM must match height taskId=" + taskId
                                    + ", stackId" + stackId, aTaskBounds.getHeight(),
                            wTaskBounds.getHeight());
                    assertEquals("Task bounds must match stack bounds y taskId=" + taskId
                                    + ", stackId" + stackId, aTaskBounds.getY(),
                            wTaskBounds.getY());
                    assertEquals("Task and stack bounds must match width taskId=" + taskId
                                    + ", stackId" + stackId, aStackBounds.getWidth(),
                            wTaskBounds.getWidth());
                    assertEquals("Task and stack bounds must match height taskId=" + taskId
                                    + ", stackId" + stackId, aStackBounds.getHeight(),
                            wTaskBounds.getHeight());
                    assertEquals("Task and stack bounds must match y taskId=" + taskId
                                    + ", stackId" + stackId, aStackBounds.getY(),
                            wTaskBounds.getY());
                } else {
                    assertEquals("Task bounds in AM and WM must be equal taskId=" + taskId
                            + ", stackId=" + stackId, aTaskBounds, wTaskBounds);

                    if (compareTaskAndStackBounds && stackId != FREEFORM_WORKSPACE_STACK_ID) {
                        int aTaskMinWidth = aTask.getMinWidth();
                        int aTaskMinHeight = aTask.getMinHeight();

                        if (aTaskMinWidth == -1 || aTaskMinHeight == -1) {
                            // Minimal dimension(s) not set for task - it should be using defaults.
                            int defaultMinimalSize = (stackId == PINNED_STACK_ID)
                                    ? defaultMinimalPinnedTaskSize(aStack.mDisplayId)
                                    : defaultMinimalTaskSize(aStack.mDisplayId);

                            if (aTaskMinWidth == -1) {
                                aTaskMinWidth = defaultMinimalSize;
                            }
                            if (aTaskMinHeight == -1) {
                                aTaskMinHeight = defaultMinimalSize;
                            }
                        }

                        if (aStackBounds.getWidth() >= aTaskMinWidth
                                && aStackBounds.getHeight() >= aTaskMinHeight
                                || stackId == PINNED_STACK_ID) {
                            // Bounds are not smaller then minimal possible, so stack and task
                            // bounds must be equal.
                            assertEquals("Task bounds must be equal to stack bounds taskId="
                                    + taskId + ", stackId=" + stackId, aStackBounds, wTaskBounds);
                        } else if (stackId == DOCKED_STACK_ID && homeStackIsResizable
                                && mWmState.isDockedStackMinimized()) {
                            // Portrait if the display height is larger than the width
                            if (displayRect.getHeight() > displayRect.getWidth()) {
                                assertEquals("Task width must be equal to stack width taskId="
                                        + taskId + ", stackId=" + stackId,
                                        aStackBounds.getWidth(), wTaskBounds.getWidth());
                                assertTrue("Task height must be greater than stack height "
                                        + "taskId=" + taskId + ", stackId=" + stackId,
                                        aStackBounds.getHeight() < wTaskBounds.getHeight());
                                assertEquals("Task and stack x position must be equal taskId="
                                        + taskId + ", stackId=" + stackId,
                                        wTaskBounds.getX(), wStackBounds.getX());
                            } else {
                                assertTrue("Task width must be greater than stack width taskId="
                                        + taskId + ", stackId=" + stackId,
                                        aStackBounds.getWidth() < wTaskBounds.getWidth());
                                assertEquals("Task height must be equal to stack height taskId="
                                        + taskId + ", stackId=" + stackId,
                                        aStackBounds.getHeight(), wTaskBounds.getHeight());
                                assertEquals("Task and stack y position must be equal taskId="
                                        + taskId + ", stackId=" + stackId, wTaskBounds.getY(),
                                        wStackBounds.getY());
                            }
                        } else {
                            // Minimal dimensions affect task size, so bounds of task and stack must
                            // be different - will compare dimensions instead.
                            int targetWidth = (int) Math.max(aTaskMinWidth,
                                    aStackBounds.getWidth());
                            assertEquals("Task width must be set according to minimal width"
                                            + " taskId=" + taskId + ", stackId=" + stackId,
                                    targetWidth, (int) wTaskBounds.getWidth());
                            int targetHeight = (int) Math.max(aTaskMinHeight,
                                    aStackBounds.getHeight());
                            assertEquals("Task height must be set according to minimal height"
                                            + " taskId=" + taskId + ", stackId=" + stackId,
                                    targetHeight, (int) wTaskBounds.getHeight());
                        }
                    }
                }
            }
        }
    }

    static int dpToPx(float dp, int densityDpi){
        return (int) (dp * densityDpi / DISPLAY_DENSITY_DEFAULT + 0.5f);
    }

    private int defaultMinimalTaskSize(int displayId) {
        return dpToPx(DEFAULT_RESIZABLE_TASK_SIZE_DP, mWmState.getDisplay(displayId).getDpi());
    }

    private int defaultMinimalPinnedTaskSize(int displayId) {
        return dpToPx(DEFAULT_PIP_RESIZABLE_TASK_SIZE_DP, mWmState.getDisplay(displayId).getDpi());
    }
}
