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

package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
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_REVERSE_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;

import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Build;
import android.util.Slog;
import android.view.Gravity;
import android.view.View;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.LaunchParamsController.LaunchParams;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;

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

/**
 * The class that defines the default launch params for tasks.
 */
class TaskLaunchParamsModifier implements LaunchParamsModifier {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_ATM;
    private static final boolean DEBUG = false;

    // A mask for SUPPORTS_SCREEN that indicates the activity supports resize.
    private static final int SUPPORTS_SCREEN_RESIZEABLE_MASK =
            ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
                    | ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
                    | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
                    | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
                    | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
                    | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;

    // Screen size of Nexus 5x
    private static final int DEFAULT_PORTRAIT_PHONE_WIDTH_DP = 412;
    private static final int DEFAULT_PORTRAIT_PHONE_HEIGHT_DP = 732;

    // Allowance of size matching.
    private static final int EPSILON = 2;

    // Cascade window offset.
    private static final int CASCADING_OFFSET_DP = 75;

    // Threshold how close window corners have to be to call them colliding.
    private static final int BOUNDS_CONFLICT_THRESHOLD = 4;

    // Divide display size by this number to get each step to adjust bounds to avoid conflict.
    private static final int STEP_DENOMINATOR = 16;

    // We always want to step by at least this.
    private static final int MINIMAL_STEP = 1;

    private final ActivityStackSupervisor mSupervisor;
    private final Rect mTmpBounds = new Rect();
    private final int[] mTmpDirections = new int[2];

    private StringBuilder mLogBuilder;

    TaskLaunchParamsModifier(ActivityStackSupervisor supervisor) {
        mSupervisor = supervisor;
    }

    @VisibleForTesting
    int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout, ActivityRecord activity,
            ActivityRecord source, ActivityOptions options, LaunchParams currentParams,
            LaunchParams outParams) {
        return onCalculate(task, layout, activity, source, options, PHASE_BOUNDS, currentParams,
                outParams);
    }

    @Override
    public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
                           ActivityRecord activity, ActivityRecord source, ActivityOptions options,
                           int phase, LaunchParams currentParams, LaunchParams outParams) {
        initLogBuilder(task, activity);
        final int result = calculate(task, layout, activity, source, options, phase, currentParams,
                outParams);
        outputLog();
        return result;
    }

    private int calculate(TaskRecord task, ActivityInfo.WindowLayout layout,
            ActivityRecord activity, ActivityRecord source, ActivityOptions options, int phase,
            LaunchParams currentParams, LaunchParams outParams) {
        final ActivityRecord root;
        if (task != null) {
            root = task.getRootActivity() == null ? activity : task.getRootActivity();
        } else {
            root = activity;
        }

        // TODO: Investigate whether we can safely ignore all cases where we don't have root
        // activity available. Note we can't know if the bounds are valid if we're not sure of the
        // requested orientation of the root activity. Therefore if we found such a case we may need
        // to pass the activity into this modifier in that case.
        if (root == null) {
            // There is a case that can lead us here. The caller is moving the top activity that is
            // in a task that has multiple activities to PIP mode. For that the caller is creating a
            // new task to host the activity so that we only move the top activity to PIP mode and
            // keep other activities in the previous task. There is no point to apply the launch
            // logic in this case.
            return RESULT_SKIP;
        }

        // STEP 1: Determine the display to launch the activity/task.
        final int displayId = getPreferredLaunchDisplay(task, options, source, currentParams);
        outParams.mPreferredDisplayId = displayId;
        ActivityDisplay display = mSupervisor.mRootActivityContainer.getActivityDisplay(displayId);
        if (DEBUG) {
            appendLog("display-id=" + outParams.mPreferredDisplayId + " display-windowing-mode="
                    + display.getWindowingMode());
        }

        if (phase == PHASE_DISPLAY) {
            return RESULT_CONTINUE;
        }

        // STEP 2: Resolve launch windowing mode.
        // STEP 2.1: Determine if any parameter has specified initial bounds. That might be the
        // launch bounds from activity options, or size/gravity passed in layout. It also treats the
        // launch windowing mode in options as a suggestion for future resolution.
        int launchMode = options != null ? options.getLaunchWindowingMode()
                : WINDOWING_MODE_UNDEFINED;
        // hasInitialBounds is set if either activity options or layout has specified bounds. If
        // that's set we'll skip some adjustments later to avoid overriding the initial bounds.
        boolean hasInitialBounds = false;
        final boolean canApplyFreeformPolicy = canApplyFreeformWindowPolicy(display, launchMode);
        if (mSupervisor.canUseActivityOptionsLaunchBounds(options)
                && (canApplyFreeformPolicy || canApplyPipWindowPolicy(launchMode))) {
            hasInitialBounds = true;
            launchMode = launchMode == WINDOWING_MODE_UNDEFINED
                    ? WINDOWING_MODE_FREEFORM
                    : launchMode;
            outParams.mBounds.set(options.getLaunchBounds());
            if (DEBUG) appendLog("activity-options-bounds=" + outParams.mBounds);
        } else if (launchMode == WINDOWING_MODE_PINNED) {
            // System controls PIP window's bounds, so don't apply launch bounds.
            if (DEBUG) appendLog("empty-window-layout-for-pip");
        } else if (launchMode == WINDOWING_MODE_FULLSCREEN) {
            if (DEBUG) appendLog("activity-options-fullscreen=" + outParams.mBounds);
        } else if (layout != null && canApplyFreeformPolicy) {
            getLayoutBounds(display, root, layout, mTmpBounds);
            if (!mTmpBounds.isEmpty()) {
                launchMode = WINDOWING_MODE_FREEFORM;
                outParams.mBounds.set(mTmpBounds);
                hasInitialBounds = true;
                if (DEBUG) appendLog("bounds-from-layout=" + outParams.mBounds);
            } else {
                if (DEBUG) appendLog("empty-window-layout");
            }
        }

        // STEP 2.2: Check if previous modifier or the controller (referred as "callers" below) has
        // some opinions on launch mode and launch bounds. If they have opinions and there is no
        // initial bounds set in parameters. Note the check on display ID is also input param
        // related because we always defer to callers' suggestion if there is no specific display ID
        // in options or from source activity.
        //
        // If opinions from callers don't need any further resolution, we try to honor that as is as
        // much as possible later.

        // Flag to indicate if current param needs no further resolution. It's true it current
        // param isn't freeform mode, or it already has launch bounds.
        boolean fullyResolvedCurrentParam = false;
        // We inherit launch params from previous modifiers or LaunchParamsController if options,
        // layout and display conditions are not contradictory to their suggestions. It's important
        // to carry over their values because LaunchParamsController doesn't automatically do that.
        if (!currentParams.isEmpty() && !hasInitialBounds
                && (!currentParams.hasPreferredDisplay()
                    || displayId == currentParams.mPreferredDisplayId)) {
            if (currentParams.hasWindowingMode()) {
                launchMode = currentParams.mWindowingMode;
                fullyResolvedCurrentParam = launchMode != WINDOWING_MODE_FREEFORM;
                if (DEBUG) {
                    appendLog("inherit-" + WindowConfiguration.windowingModeToString(launchMode));
                }
            }

            if (!currentParams.mBounds.isEmpty()) {
                // Carry over bounds from callers regardless of launch mode because bounds is still
                // used to restore last non-fullscreen bounds when launch mode is not freeform.
                // Therefore it's not a resolution step for non-freeform launch mode and only
                // consider it fully resolved only when launch mode is freeform.
                outParams.mBounds.set(currentParams.mBounds);
                if (launchMode == WINDOWING_MODE_FREEFORM) {
                    fullyResolvedCurrentParam = true;
                    if (DEBUG) appendLog("inherit-bounds=" + outParams.mBounds);
                }
            }
        }

        // STEP 2.3: Adjust launch parameters as needed for freeform display. We enforce the policy
        // that legacy (pre-D) apps and those apps that can't handle multiple screen density well
        // are forced to be maximized. The rest of this step is to define the default policy when
        // there is no initial bounds or a fully resolved current params from callers.
        if (display.inFreeformWindowingMode()) {
            if (launchMode == WINDOWING_MODE_PINNED) {
                if (DEBUG) appendLog("picture-in-picture");
            } else if (isTaskForcedMaximized(root)) {
                // We're launching an activity that probably can't handle resizing nicely, so force
                // it to be maximized even someone suggests launching it in freeform using launch
                // options.
                launchMode = WINDOWING_MODE_FULLSCREEN;
                outParams.mBounds.setEmpty();
                if (DEBUG) appendLog("forced-maximize");
            }
        } else {
            if (DEBUG) appendLog("non-freeform-display");
        }
        // If launch mode matches display windowing mode, let it inherit from display.
        outParams.mWindowingMode = launchMode == display.getWindowingMode()
                ? WINDOWING_MODE_UNDEFINED : launchMode;

        if (phase == PHASE_WINDOWING_MODE) {
            return RESULT_CONTINUE;
        }

        // STEP 3: Determine final launch bounds based on resolved windowing mode and activity
        // requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
        // for all other windowing modes that's not freeform mode. One can read comments in
        // relevant methods to further understand this step.
        //
        // We skip making adjustments if the params are fully resolved from previous results.
        final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
                : display.getWindowingMode();
        if (fullyResolvedCurrentParam) {
            if (resolvedMode == WINDOWING_MODE_FREEFORM) {
                // Make sure bounds are in the display if it's possibly in a different display.
                if (currentParams.mPreferredDisplayId != displayId) {
                    adjustBoundsToFitInDisplay(display, outParams.mBounds);
                }
                // Even though we want to keep original bounds, we still don't want it to stomp on
                // an existing task.
                adjustBoundsToAvoidConflictInDisplay(display, outParams.mBounds);
            }
        } else {
            if (source != null && source.inFreeformWindowingMode()
                    && resolvedMode == WINDOWING_MODE_FREEFORM
                    && outParams.mBounds.isEmpty()
                    && source.getDisplayId() == display.mDisplayId) {
                // Set bounds to be not very far from source activity.
                cascadeBounds(source.getBounds(), display, outParams.mBounds);
            }
            getTaskBounds(root, display, layout, resolvedMode, hasInitialBounds, outParams.mBounds);
        }

        return RESULT_CONTINUE;
    }

    private int getPreferredLaunchDisplay(@Nullable TaskRecord task,
            @Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams) {
        if (!mSupervisor.mService.mSupportsMultiDisplay) {
            return DEFAULT_DISPLAY;
        }

        int displayId = INVALID_DISPLAY;
        final int optionLaunchId = options != null ? options.getLaunchDisplayId() : INVALID_DISPLAY;
        if (optionLaunchId != INVALID_DISPLAY) {
            if (DEBUG) appendLog("display-from-option=" + optionLaunchId);
            displayId = optionLaunchId;
        }

        // If the source activity is a no-display activity, pass on the launch display id from
        // source activity as currently preferred.
        if (displayId == INVALID_DISPLAY && source != null && source.noDisplay) {
            displayId = source.mHandoverLaunchDisplayId;
            if (DEBUG) appendLog("display-from-no-display-source=" + displayId);
        }

        ActivityStack stack =
                (displayId == INVALID_DISPLAY && task != null) ? task.getStack() : null;
        if (stack != null) {
            if (DEBUG) appendLog("display-from-task=" + stack.mDisplayId);
            displayId = stack.mDisplayId;
        }

        if (displayId == INVALID_DISPLAY && source != null) {
            final int sourceDisplayId = source.getDisplayId();
            if (DEBUG) appendLog("display-from-source=" + sourceDisplayId);
            displayId = sourceDisplayId;
        }

        if (displayId != INVALID_DISPLAY
                && mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) == null) {
            displayId = currentParams.mPreferredDisplayId;
        }
        displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId;

        return (displayId != INVALID_DISPLAY
                && mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) != null)
                ? displayId : DEFAULT_DISPLAY;
    }

    private boolean canApplyFreeformWindowPolicy(@NonNull ActivityDisplay display, int launchMode) {
        return mSupervisor.mService.mSupportsFreeformWindowManagement
                && (display.inFreeformWindowingMode() || launchMode == WINDOWING_MODE_FREEFORM);
    }

    private boolean canApplyPipWindowPolicy(int launchMode) {
        return mSupervisor.mService.mSupportsPictureInPicture
                && launchMode == WINDOWING_MODE_PINNED;
    }

    private void getLayoutBounds(@NonNull ActivityDisplay display, @NonNull ActivityRecord root,
            @NonNull ActivityInfo.WindowLayout windowLayout, @NonNull Rect outBounds) {
        final int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
        final int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
        if (!windowLayout.hasSpecifiedSize() && verticalGravity == 0 && horizontalGravity == 0) {
            outBounds.setEmpty();
            return;
        }

        final Rect bounds = display.getBounds();
        final int defaultWidth = bounds.width();
        final int defaultHeight = bounds.height();

        int width;
        int height;
        if (!windowLayout.hasSpecifiedSize()) {
            outBounds.setEmpty();
            getTaskBounds(root, display, windowLayout, WINDOWING_MODE_FREEFORM,
                    /* hasInitialBounds */ false, outBounds);
            width = outBounds.width();
            height = outBounds.height();
        } else {
            width = defaultWidth;
            if (windowLayout.width > 0 && windowLayout.width < defaultWidth) {
                width = windowLayout.width;
            } else if (windowLayout.widthFraction > 0 && windowLayout.widthFraction < 1.0f) {
                width = (int) (width * windowLayout.widthFraction);
            }

            height = defaultHeight;
            if (windowLayout.height > 0 && windowLayout.height < defaultHeight) {
                height = windowLayout.height;
            } else if (windowLayout.heightFraction > 0 && windowLayout.heightFraction < 1.0f) {
                height = (int) (height * windowLayout.heightFraction);
            }
        }

        final float fractionOfHorizontalOffset;
        switch (horizontalGravity) {
            case Gravity.LEFT:
                fractionOfHorizontalOffset = 0f;
                break;
            case Gravity.RIGHT:
                fractionOfHorizontalOffset = 1f;
                break;
            default:
                fractionOfHorizontalOffset = 0.5f;
        }

        final float fractionOfVerticalOffset;
        switch (verticalGravity) {
            case Gravity.TOP:
                fractionOfVerticalOffset = 0f;
                break;
            case Gravity.BOTTOM:
                fractionOfVerticalOffset = 1f;
                break;
            default:
                fractionOfVerticalOffset = 0.5f;
        }

        outBounds.set(0, 0, width, height);
        final int xOffset = (int) (fractionOfHorizontalOffset * (defaultWidth - width));
        final int yOffset = (int) (fractionOfVerticalOffset * (defaultHeight - height));
        outBounds.offset(xOffset, yOffset);
    }

    /**
     * Returns if task is forced to maximize.
     *
     * There are several cases where we force a task to maximize:
     * 1) Root activity is targeting pre-Donut, which by default can't handle multiple screen
     *    densities, so resizing will likely cause issues;
     * 2) Root activity doesn't declare any flag that it supports any screen density, so resizing
     *    may also cause issues;
     * 3) Root activity is not resizeable, for which we shouldn't allow user resize it.
     *
     * @param root the root activity to check against.
     * @return {@code true} if it should be forced to maximize; {@code false} otherwise.
     */
    private boolean isTaskForcedMaximized(@NonNull ActivityRecord root) {
        if (root.appInfo.targetSdkVersion < Build.VERSION_CODES.DONUT
                || (root.appInfo.flags & SUPPORTS_SCREEN_RESIZEABLE_MASK) == 0) {
            return true;
        }

        return !root.isResizeable();
    }

    /**
     * Resolves activity requested orientation to 4 categories:
     * 1) {@link ActivityInfo#SCREEN_ORIENTATION_LOCKED} indicating app wants to lock down
     *    orientation;
     * 2) {@link ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE} indicating app wants to be in landscape;
     * 3) {@link ActivityInfo#SCREEN_ORIENTATION_PORTRAIT} indicating app wants to be in portrait;
     * 4) {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} indicating app can handle any
     *    orientation.
     *
     * @param activity the activity to check
     * @return corresponding resolved orientation value.
     */
    private int resolveOrientation(@NonNull ActivityRecord activity) {
        int orientation = activity.info.screenOrientation;
        switch (orientation) {
            case SCREEN_ORIENTATION_NOSENSOR:
            case SCREEN_ORIENTATION_LOCKED:
                orientation = SCREEN_ORIENTATION_LOCKED;
                break;
            case SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
            case SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
            case SCREEN_ORIENTATION_USER_LANDSCAPE:
            case SCREEN_ORIENTATION_LANDSCAPE:
                if (DEBUG) appendLog("activity-requested-landscape");
                orientation = SCREEN_ORIENTATION_LANDSCAPE;
                break;
            case SCREEN_ORIENTATION_SENSOR_PORTRAIT:
            case SCREEN_ORIENTATION_REVERSE_PORTRAIT:
            case SCREEN_ORIENTATION_USER_PORTRAIT:
            case SCREEN_ORIENTATION_PORTRAIT:
                if (DEBUG) appendLog("activity-requested-portrait");
                orientation = SCREEN_ORIENTATION_PORTRAIT;
                break;
            default:
                orientation = SCREEN_ORIENTATION_UNSPECIFIED;
        }

        return orientation;
    }

    private void cascadeBounds(@NonNull Rect srcBounds, @NonNull ActivityDisplay display,
            @NonNull Rect outBounds) {
        outBounds.set(srcBounds);
        float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
        final int defaultOffset = (int) (CASCADING_OFFSET_DP * density + 0.5f);

        display.getBounds(mTmpBounds);
        final int dx = Math.min(defaultOffset, Math.max(0, mTmpBounds.right - srcBounds.right));
        final int dy = Math.min(defaultOffset, Math.max(0, mTmpBounds.bottom - srcBounds.bottom));
        outBounds.offset(dx, dy);
    }

    private void getTaskBounds(@NonNull ActivityRecord root, @NonNull ActivityDisplay display,
            @NonNull ActivityInfo.WindowLayout layout, int resolvedMode, boolean hasInitialBounds,
            @NonNull Rect inOutBounds) {
        if (resolvedMode == WINDOWING_MODE_FULLSCREEN) {
            // We don't handle letterboxing here. Letterboxing will be handled by valid checks
            // later.
            inOutBounds.setEmpty();
            if (DEBUG) appendLog("maximized-bounds");
            return;
        }

        if (resolvedMode != WINDOWING_MODE_FREEFORM) {
            // We don't apply freeform bounds adjustment to other windowing modes.
            if (DEBUG) {
                appendLog("skip-bounds-" + WindowConfiguration.windowingModeToString(resolvedMode));
            }
            return;
        }

        final int orientation = resolveOrientation(root, display, inOutBounds);
        if (orientation != SCREEN_ORIENTATION_PORTRAIT
                && orientation != SCREEN_ORIENTATION_LANDSCAPE) {
            throw new IllegalStateException(
                    "Orientation must be one of portrait or landscape, but it's "
                    + ActivityInfo.screenOrientationToString(orientation));
        }

        // First we get the default size we want.
        getDefaultFreeformSize(display, layout, orientation, mTmpBounds);
        if (hasInitialBounds || sizeMatches(inOutBounds, mTmpBounds)) {
            // We're here because either input parameters specified initial bounds, or the suggested
            // bounds have the same size of the default freeform size. We should use the suggested
            // bounds if possible -- so if app can handle the orientation we just use it, and if not
            // we transpose the suggested bounds in-place.
            if (orientation == orientationFromBounds(inOutBounds)) {
                if (DEBUG) appendLog("freeform-size-orientation-match=" + inOutBounds);
            } else {
                // Meh, orientation doesn't match. Let's rotate inOutBounds in-place.
                centerBounds(display, inOutBounds.height(), inOutBounds.width(), inOutBounds);
                if (DEBUG) appendLog("freeform-orientation-mismatch=" + inOutBounds);
            }
        } else {
            // We are here either because there is no suggested bounds, or the suggested bounds is
            // a cascade from source activity. We should use the default freeform size and center it
            // to the center of suggested bounds (or the display if no suggested bounds). The
            // default size might be too big to center to source activity bounds in display, so we
            // may need to move it back to the display.
            centerBounds(display, mTmpBounds.width(), mTmpBounds.height(), inOutBounds);
            adjustBoundsToFitInDisplay(display, inOutBounds);
            if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds);
        }

        // Lastly we adjust bounds to avoid conflicts with other tasks as much as possible.
        adjustBoundsToAvoidConflictInDisplay(display, inOutBounds);
    }

    private int convertOrientationToScreenOrientation(int orientation) {
        switch (orientation) {
            case Configuration.ORIENTATION_LANDSCAPE:
                return SCREEN_ORIENTATION_LANDSCAPE;
            case Configuration.ORIENTATION_PORTRAIT:
                return SCREEN_ORIENTATION_PORTRAIT;
            default:
                return SCREEN_ORIENTATION_UNSPECIFIED;
        }
    }

    private int resolveOrientation(@NonNull ActivityRecord root, @NonNull ActivityDisplay display,
            @NonNull Rect bounds) {
        int orientation = resolveOrientation(root);

        if (orientation == SCREEN_ORIENTATION_LOCKED) {
            orientation = bounds.isEmpty()
                    ? convertOrientationToScreenOrientation(display.getConfiguration().orientation)
                    : orientationFromBounds(bounds);
            if (DEBUG) {
                appendLog(bounds.isEmpty() ? "locked-orientation-from-display=" + orientation
                        : "locked-orientation-from-bounds=" + bounds);
            }
        }

        if (orientation == SCREEN_ORIENTATION_UNSPECIFIED) {
            orientation = bounds.isEmpty() ? SCREEN_ORIENTATION_PORTRAIT
                    : orientationFromBounds(bounds);
            if (DEBUG) {
                appendLog(bounds.isEmpty() ? "default-portrait"
                        : "orientation-from-bounds=" + bounds);
            }
        }

        return orientation;
    }

    private void getDefaultFreeformSize(@NonNull ActivityDisplay display,
            @NonNull ActivityInfo.WindowLayout layout, int orientation, @NonNull Rect bounds) {
        // Default size, which is letterboxing/pillarboxing in display. That's to say the large
        // dimension of default size is the small dimension of display size, and the small dimension
        // of default size is calculated to keep the same aspect ratio as the display's.
        Rect displayBounds = display.getBounds();
        final int portraitHeight = Math.min(displayBounds.width(), displayBounds.height());
        final int otherDimension = Math.max(displayBounds.width(), displayBounds.height());
        final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension;
        final int defaultWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight
                : portraitWidth;
        final int defaultHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitWidth
                : portraitHeight;

        // Get window size based on Nexus 5x screen, we assume that this is enough to show content
        // of activities.
        final float density = (float) display.getConfiguration().densityDpi / DENSITY_DEFAULT;
        final int phonePortraitWidth = (int) (DEFAULT_PORTRAIT_PHONE_WIDTH_DP * density + 0.5f);
        final int phonePortraitHeight = (int) (DEFAULT_PORTRAIT_PHONE_HEIGHT_DP * density + 0.5f);
        final int phoneWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitHeight
                : phonePortraitWidth;
        final int phoneHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitWidth
                : phonePortraitHeight;

        // Minimum layout requirements.
        final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth;
        final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;

        // Final result.
        final int width = Math.min(defaultWidth, Math.max(phoneWidth, layoutMinWidth));
        final int height = Math.min(defaultHeight, Math.max(phoneHeight, layoutMinHeight));

        bounds.set(0, 0, width, height);
    }

    /**
     * Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds
     * centers at its center or display's center if inOutBounds is empty.
     */
    private void centerBounds(@NonNull ActivityDisplay display, int width, int height,
            @NonNull Rect inOutBounds) {
        if (inOutBounds.isEmpty()) {
            display.getBounds(inOutBounds);
        }
        final int left = inOutBounds.centerX() - width / 2;
        final int top = inOutBounds.centerY() - height / 2;
        inOutBounds.set(left, top, left + width, top + height);
    }

    private void adjustBoundsToFitInDisplay(@NonNull ActivityDisplay display,
            @NonNull Rect inOutBounds) {
        final Rect displayBounds = display.getBounds();

        if (displayBounds.width() < inOutBounds.width()
                || displayBounds.height() < inOutBounds.height()) {
            // There is no way for us to fit the bounds in the display without changing width
            // or height. Just move the start to align with the display.
            final int layoutDirection =
                    mSupervisor.mRootActivityContainer.getConfiguration().getLayoutDirection();
            final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
                    ? displayBounds.width() - inOutBounds.width()
                    : 0;
            inOutBounds.offsetTo(left, 0 /* newTop */);
            return;
        }

        final int dx;
        if (inOutBounds.right > displayBounds.right) {
            // Right edge is out of display.
            dx = displayBounds.right - inOutBounds.right;
        } else if (inOutBounds.left < displayBounds.left) {
            // Left edge is out of display.
            dx = displayBounds.left - inOutBounds.left;
        } else {
            // Vertical edges are all in display.
            dx = 0;
        }

        final int dy;
        if (inOutBounds.top < displayBounds.top) {
            // Top edge is out of display.
            dy = displayBounds.top - inOutBounds.top;
        } else if (inOutBounds.bottom > displayBounds.bottom) {
            // Bottom edge is out of display.
            dy = displayBounds.bottom - inOutBounds.bottom;
        } else {
            // Horizontal edges are all in display.
            dy = 0;
        }
        inOutBounds.offset(dx, dy);
    }

    /**
     * Adjusts input bounds to avoid conflict with existing tasks in the display.
     *
     * If the input bounds conflict with existing tasks, this method scans the bounds in a series of
     * directions to find a location where the we can put the bounds in display without conflict
     * with any other tasks.
     *
     * It doesn't try to adjust bounds that's not fully in the given display.
     *
     * @param display the display which tasks are to check
     * @param inOutBounds the bounds used to input initial bounds and output result bounds
     */
    private void adjustBoundsToAvoidConflictInDisplay(@NonNull ActivityDisplay display,
            @NonNull Rect inOutBounds) {
        final List<Rect> taskBoundsToCheck = new ArrayList<>();
        for (int i = 0; i < display.getChildCount(); ++i) {
            final ActivityStack stack = display.getChildAt(i);
            if (!stack.inFreeformWindowingMode()) {
                continue;
            }

            for (int j = 0; j < stack.getChildCount(); ++j) {
                taskBoundsToCheck.add(stack.getChildAt(j).getBounds());
            }
        }
        adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds);
    }

    /**
     * Adjusts input bounds to avoid conflict with provided display bounds and list of tasks bounds
     * for the display.
     *
     * Scans the bounds in directions to find a candidate location that does not conflict with the
     * provided list of task bounds. If starting bounds are outside the display bounds or if no
     * suitable candidate bounds are found, the method returns the input bounds.
     *
     * @param displayBounds display bounds used to restrict the candidate bounds
     * @param taskBoundsToCheck list of task bounds to check for conflict
     * @param inOutBounds the bounds used to input initial bounds and output result bounds
     */
    @VisibleForTesting
    void adjustBoundsToAvoidConflict(@NonNull Rect displayBounds,
            @NonNull List<Rect> taskBoundsToCheck,
            @NonNull Rect inOutBounds) {
        if (!displayBounds.contains(inOutBounds)) {
            // The initial bounds are already out of display. The scanning algorithm below doesn't
            // work so well with them.
            return;
        }

        if (!boundsConflict(taskBoundsToCheck, inOutBounds)) {
            // Current proposal doesn't conflict with any task. Early return to avoid unnecessary
            // calculation.
            return;
        }

        calculateCandidateShiftDirections(displayBounds, inOutBounds);
        for (int direction : mTmpDirections) {
            if (direction == Gravity.NO_GRAVITY) {
                // We exhausted candidate directions, give up.
                break;
            }

            mTmpBounds.set(inOutBounds);
            while (boundsConflict(taskBoundsToCheck, mTmpBounds)
                    && displayBounds.contains(mTmpBounds)) {
                shiftBounds(direction, displayBounds, mTmpBounds);
            }

            if (!boundsConflict(taskBoundsToCheck, mTmpBounds)
                    && displayBounds.contains(mTmpBounds)) {
                // Found a candidate. Just use this.
                inOutBounds.set(mTmpBounds);
                if (DEBUG) appendLog("avoid-bounds-conflict=" + inOutBounds);
                return;
            }

            // Didn't find a conflict free bounds here. Try the next candidate direction.
        }

        // We failed to find a conflict free location. Just keep the original result.
    }

    /**
     * Determines scanning directions and their priorities to avoid bounds conflict.
     *
     * @param availableBounds bounds that the result must be in
     * @param initialBounds initial bounds when start scanning
     */
    private void calculateCandidateShiftDirections(@NonNull Rect availableBounds,
            @NonNull Rect initialBounds) {
        for (int i = 0; i < mTmpDirections.length; ++i) {
            mTmpDirections[i] = Gravity.NO_GRAVITY;
        }

        final int oneThirdWidth = (2 * availableBounds.left + availableBounds.right) / 3;
        final int twoThirdWidth = (availableBounds.left + 2 * availableBounds.right) / 3;
        final int centerX = initialBounds.centerX();
        if (centerX < oneThirdWidth) {
            // Too close to left, just scan to the right.
            mTmpDirections[0] = Gravity.RIGHT;
            return;
        } else if (centerX > twoThirdWidth) {
            // Too close to right, just scan to the left.
            mTmpDirections[0] = Gravity.LEFT;
            return;
        }

        final int oneThirdHeight = (2 * availableBounds.top + availableBounds.bottom) / 3;
        final int twoThirdHeight = (availableBounds.top + 2 * availableBounds.bottom) / 3;
        final int centerY = initialBounds.centerY();
        if (centerY < oneThirdHeight || centerY > twoThirdHeight) {
            // Too close to top or bottom boundary and we're in the middle horizontally, scan
            // horizontally in both directions.
            mTmpDirections[0] = Gravity.RIGHT;
            mTmpDirections[1] = Gravity.LEFT;
            return;
        }

        // We're in the center region both horizontally and vertically. Scan in both directions of
        // primary diagonal.
        mTmpDirections[0] = Gravity.BOTTOM | Gravity.RIGHT;
        mTmpDirections[1] = Gravity.TOP | Gravity.LEFT;
    }

    private boolean boundsConflict(@NonNull List<Rect> taskBoundsToCheck,
                                   @NonNull Rect candidateBounds) {
        for (Rect taskBounds : taskBoundsToCheck) {
            final boolean leftClose = Math.abs(taskBounds.left - candidateBounds.left)
                    < BOUNDS_CONFLICT_THRESHOLD;
            final boolean topClose = Math.abs(taskBounds.top - candidateBounds.top)
                    < BOUNDS_CONFLICT_THRESHOLD;
            final boolean rightClose = Math.abs(taskBounds.right - candidateBounds.right)
                    < BOUNDS_CONFLICT_THRESHOLD;
            final boolean bottomClose = Math.abs(taskBounds.bottom - candidateBounds.bottom)
                    < BOUNDS_CONFLICT_THRESHOLD;

            if ((leftClose && topClose) || (leftClose && bottomClose) || (rightClose && topClose)
                    || (rightClose && bottomClose)) {
                return true;
            }
        }

        return false;
    }

    private void shiftBounds(int direction, @NonNull Rect availableRect,
            @NonNull Rect inOutBounds) {
        final int horizontalOffset;
        switch (direction & Gravity.HORIZONTAL_GRAVITY_MASK) {
            case Gravity.LEFT:
                horizontalOffset = -Math.max(MINIMAL_STEP,
                        availableRect.width() / STEP_DENOMINATOR);
                break;
            case Gravity.RIGHT:
                horizontalOffset = Math.max(MINIMAL_STEP, availableRect.width() / STEP_DENOMINATOR);
                break;
            default:
                horizontalOffset = 0;
        }

        final int verticalOffset;
        switch (direction & Gravity.VERTICAL_GRAVITY_MASK) {
            case Gravity.TOP:
                verticalOffset = -Math.max(MINIMAL_STEP, availableRect.height() / STEP_DENOMINATOR);
                break;
            case Gravity.BOTTOM:
                verticalOffset = Math.max(MINIMAL_STEP, availableRect.height() / STEP_DENOMINATOR);
                break;
            default:
                verticalOffset = 0;
        }

        inOutBounds.offset(horizontalOffset, verticalOffset);
    }

    private void initLogBuilder(TaskRecord task, ActivityRecord activity) {
        if (DEBUG) {
            mLogBuilder = new StringBuilder("TaskLaunchParamsModifier:task=" + task
                    + " activity=" + activity);
        }
    }

    private void appendLog(String log) {
        if (DEBUG) mLogBuilder.append(" ").append(log);
    }

    private void outputLog() {
        if (DEBUG) Slog.d(TAG, mLogBuilder.toString());
    }

    private static int orientationFromBounds(Rect bounds) {
        return bounds.width() > bounds.height() ? SCREEN_ORIENTATION_LANDSCAPE
                : SCREEN_ORIENTATION_PORTRAIT;
    }

    private static boolean sizeMatches(Rect left, Rect right) {
        return (Math.abs(right.width() - left.width()) < EPSILON)
                && (Math.abs(right.height() - left.height()) < EPSILON);
    }
}
