/*
 * 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.ActivityTaskManager.RESIZE_MODE_USER;
import static android.app.ActivityTaskManager.RESIZE_MODE_USER_FORCED;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;

import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;

import android.annotation.IntDef;
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.Display;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputWindowHandle;
import android.view.MotionEvent;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForTesting;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

class TaskPositioner {
    private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
    private static final String TAG_LOCAL = "TaskPositioner";
    private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;

    private static Factory sFactory;

    // The margin the pointer position has to be within the side of the screen to be
    // considered at the side of the screen.
    static final int SIDE_MARGIN_DIP = 100;

    @IntDef(flag = true,
            value = {
                    CTRL_NONE,
                    CTRL_LEFT,
                    CTRL_RIGHT,
                    CTRL_TOP,
                    CTRL_BOTTOM
            })
    @Retention(RetentionPolicy.SOURCE)
    @interface CtrlType {}

    private static final int CTRL_NONE   = 0x0;
    private static final int CTRL_LEFT   = 0x1;
    private static final int CTRL_RIGHT  = 0x2;
    private static final int CTRL_TOP    = 0x4;
    private static final int CTRL_BOTTOM = 0x8;

    public static final float RESIZING_HINT_ALPHA = 0.5f;

    public static final int RESIZING_HINT_DURATION_MS = 0;

    // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait).
    // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever
    // aspect he desires.
    @VisibleForTesting
    static final float MIN_ASPECT = 1.2f;

    private final WindowManagerService mService;
    private final IActivityTaskManager mActivityManager;
    private WindowPositionerEventReceiver mInputEventReceiver;
    private DisplayContent mDisplayContent;
    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
    private Rect mTmpRect = new Rect();
    private int mSideMargin;
    private int mMinVisibleWidth;
    private int mMinVisibleHeight;

    private Task mTask;
    private boolean mResizing;
    private boolean mPreserveOrientation;
    private boolean mStartOrientationWasLandscape;
    private final Rect mWindowOriginalBounds = new Rect();
    private final Rect mWindowDragBounds = new Rect();
    private final Point mMaxVisibleSize = new Point();
    private float mStartDragX;
    private float mStartDragY;
    @CtrlType
    private int mCtrlType = CTRL_NONE;
    private boolean mDragEnded = false;

    InputChannel mServerChannel;
    InputChannel mClientChannel;
    InputApplicationHandle mDragApplicationHandle;
    InputWindowHandle mDragWindowHandle;

    private final class WindowPositionerEventReceiver extends BatchedInputEventReceiver {
        public WindowPositionerEventReceiver(
                InputChannel inputChannel, Looper looper, Choreographer choreographer) {
            super(inputChannel, looper, choreographer);
        }

        @Override
        public void onInputEvent(InputEvent event) {
            if (!(event instanceof MotionEvent)
                    || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
                return;
            }
            final MotionEvent motionEvent = (MotionEvent) event;
            boolean handled = false;

            try {
                if (mDragEnded) {
                    // The drag has ended but the clean-up message has not been processed by
                    // window manager. Drop events that occur after this until window manager
                    // has a chance to clean-up the input handle.
                    handled = true;
                    return;
                }

                final float newX = motionEvent.getRawX();
                final float newY = motionEvent.getRawY();

                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN: {
                        if (DEBUG_TASK_POSITIONING) {
                            Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
                        }
                    } break;

                    case MotionEvent.ACTION_MOVE: {
                        if (DEBUG_TASK_POSITIONING){
                            Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
                        }
                        synchronized (mService.mGlobalLock) {
                            mDragEnded = notifyMoveLocked(newX, newY);
                            mTask.getDimBounds(mTmpRect);
                        }
                        if (!mTmpRect.equals(mWindowDragBounds)) {
                            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                                    "wm.TaskPositioner.resizeTask");
                            try {
                                mActivityManager.resizeTask(
                                        mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
                            } catch (RemoteException e) {
                            }
                            Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                        }
                    } break;

                    case MotionEvent.ACTION_UP: {
                        if (DEBUG_TASK_POSITIONING) {
                            Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
                        }
                        mDragEnded = true;
                    } break;

                    case MotionEvent.ACTION_CANCEL: {
                        if (DEBUG_TASK_POSITIONING) {
                            Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
                        }
                        mDragEnded = true;
                    } break;
                }

                if (mDragEnded) {
                    final boolean wasResizing = mResizing;
                    synchronized (mService.mGlobalLock) {
                        endDragLocked();
                        mTask.getDimBounds(mTmpRect);
                    }
                    try {
                        if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
                            // We were using fullscreen surface during resizing. Request
                            // resizeTask() one last time to restore surface to window size.
                            mActivityManager.resizeTask(
                                    mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
                        }
                    } catch(RemoteException e) {}

                    // Post back to WM to handle clean-ups. We still need the input
                    // event handler for the last finishInputEvent()!
                    mService.mTaskPositioningController.finishTaskPositioning();
                }
                handled = true;
            } catch (Exception e) {
                Slog.e(TAG, "Exception caught by drag handleMotion", e);
            } finally {
                finishInputEvent(event, handled);
            }
        }
    }

    @VisibleForTesting
    TaskPositioner(WindowManagerService service, IActivityTaskManager activityManager) {
        mService = service;
        mActivityManager = activityManager;
    }

    /** Use {@link #create(WindowManagerService)} instead **/
    TaskPositioner(WindowManagerService service) {
        this(service, service.mActivityTaskManager);
    }

    @VisibleForTesting
    Rect getWindowDragBounds() {
        return mWindowDragBounds;
    }

    /**
     * @param displayContent The Display that the window being dragged is on.
     */
    void register(DisplayContent displayContent) {
        final Display display = displayContent.getDisplay();

        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "Registering task positioner");
        }

        if (mClientChannel != null) {
            Slog.e(TAG, "Task positioner already registered");
            return;
        }

        mDisplayContent = displayContent;
        display.getMetrics(mDisplayMetrics);
        final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
        mServerChannel = channels[0];
        mClientChannel = channels[1];
        mService.mInputManager.registerInputChannel(mServerChannel, null);

        mInputEventReceiver = new WindowPositionerEventReceiver(
                mClientChannel, mService.mAnimationHandler.getLooper(),
                mService.mAnimator.getChoreographer());

        mDragApplicationHandle = new InputApplicationHandle(new Binder());
        mDragApplicationHandle.name = TAG;
        mDragApplicationHandle.dispatchingTimeoutNanos =
                WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;

        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
                display.getDisplayId());
        mDragWindowHandle.name = TAG;
        mDragWindowHandle.token = mServerChannel.getToken();
        mDragWindowHandle.layer = mService.getDragLayerLocked();
        mDragWindowHandle.layoutParamsFlags = 0;
        mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
        mDragWindowHandle.dispatchingTimeoutNanos =
                WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
        mDragWindowHandle.visible = true;
        mDragWindowHandle.canReceiveKeys = false;
        mDragWindowHandle.hasFocus = true;
        mDragWindowHandle.hasWallpaper = false;
        mDragWindowHandle.paused = false;
        mDragWindowHandle.ownerPid = Process.myPid();
        mDragWindowHandle.ownerUid = Process.myUid();
        mDragWindowHandle.inputFeatures = 0;
        mDragWindowHandle.scaleFactor = 1.0f;

        // The drag window cannot receive new touches.
        mDragWindowHandle.touchableRegion.setEmpty();

        // The drag window covers the entire display
        mDragWindowHandle.frameLeft = 0;
        mDragWindowHandle.frameTop = 0;
        final Point p = new Point();
        display.getRealSize(p);
        mDragWindowHandle.frameRight = p.x;
        mDragWindowHandle.frameBottom = p.y;

        // Pause rotations before a drag.
        if (DEBUG_ORIENTATION) {
            Slog.d(TAG, "Pausing rotation during re-position");
        }
        mDisplayContent.pauseRotationLocked();

        // Notify InputMonitor to take mDragWindowHandle.
        mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);

        mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
        mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
        mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
        display.getRealSize(mMaxVisibleSize);

        mDragEnded = false;
    }

    void unregister() {
        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "Unregistering task positioner");
        }

        if (mClientChannel == null) {
            Slog.e(TAG, "Task positioner not registered");
            return;
        }

        mService.mInputManager.unregisterInputChannel(mServerChannel);

        mInputEventReceiver.dispose();
        mInputEventReceiver = null;
        mClientChannel.dispose();
        mServerChannel.dispose();
        mClientChannel = null;
        mServerChannel = null;

        mDragWindowHandle = null;
        mDragApplicationHandle = null;
        mDragEnded = true;

        // Notify InputMonitor to remove mDragWindowHandle.
        mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);

        // Resume rotations after a drag.
        if (DEBUG_ORIENTATION) {
            Slog.d(TAG, "Resuming rotation after re-position");
        }
        mDisplayContent.resumeRotationLocked();
        mDisplayContent = null;
    }

    void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
                   float startY) {
        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "startDrag: win=" + win + ", resize=" + resize
                    + ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
                    + startY + "}");
        }
        mTask = win.getTask();
        // Use the bounds of the task which accounts for
        // multiple app windows. Don't use any bounds from win itself as it
        // may not be the same size as the task.
        mTask.getBounds(mTmpRect);
        startDrag(resize, preserveOrientation, startX, startY, mTmpRect);
    }

    protected void startDrag(boolean resize, boolean preserveOrientation,
                   float startX, float startY, Rect startBounds) {
        mCtrlType = CTRL_NONE;
        mStartDragX = startX;
        mStartDragY = startY;
        mPreserveOrientation = preserveOrientation;

        if (resize) {
            if (startX < startBounds.left) {
                mCtrlType |= CTRL_LEFT;
            }
            if (startX > startBounds.right) {
                mCtrlType |= CTRL_RIGHT;
            }
            if (startY < startBounds.top) {
                mCtrlType |= CTRL_TOP;
            }
            if (startY > startBounds.bottom) {
                mCtrlType |= CTRL_BOTTOM;
            }
            mResizing = mCtrlType != CTRL_NONE;
        }

        // In case of !isDockedInEffect we are using the union of all task bounds. These might be
        // made up out of multiple windows which are only partially overlapping. When that happens,
        // the orientation from the window of interest to the entire stack might diverge. However
        // for now we treat them as the same.
        mStartOrientationWasLandscape = startBounds.width() >= startBounds.height();
        mWindowOriginalBounds.set(startBounds);

        // Notify the app that resizing has started, even though we haven't received any new
        // bounds yet. This will guarantee that the app starts the backdrop renderer before
        // configuration changes which could cause an activity restart.
        if (mResizing) {
            synchronized (mService.mGlobalLock) {
                notifyMoveLocked(startX, startY);
            }

            // Perform the resize on the WMS handler thread when we don't have the WMS lock held
            // to ensure that we don't deadlock WMS and AMS. Note that WindowPositionerEventReceiver
            // callbacks are delivered on the same handler so this initial resize is always
            // guaranteed to happen before subsequent drag resizes.
            mService.mH.post(() -> {
                try {
                    mActivityManager.resizeTask(
                            mTask.mTaskId, startBounds, RESIZE_MODE_USER_FORCED);
                } catch (RemoteException e) {
                }
            });
        }

        // Make sure we always have valid drag bounds even if the drag ends before any move events
        // have been handled.
        mWindowDragBounds.set(startBounds);
    }

    private void endDragLocked() {
        mResizing = false;
        mTask.setDragResizing(false, DRAG_RESIZE_MODE_FREEFORM);
    }

    /** Returns true if the move operation should be ended. */
    private boolean notifyMoveLocked(float x, float y) {
        if (DEBUG_TASK_POSITIONING) {
            Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
        }

        if (mCtrlType != CTRL_NONE) {
            resizeDrag(x, y);
            mTask.setDragResizing(true, DRAG_RESIZE_MODE_FREEFORM);
            return false;
        }

        // This is a moving or scrolling operation.
        mTask.mStack.getDimBounds(mTmpRect);

        int nX = (int) x;
        int nY = (int) y;
        if (!mTmpRect.contains(nX, nY)) {
            // For a moving operation we allow the pointer to go out of the stack bounds, but
            // use the clamped pointer position for the drag bounds computation.
            nX = Math.min(Math.max(nX, mTmpRect.left), mTmpRect.right);
            nY = Math.min(Math.max(nY, mTmpRect.top), mTmpRect.bottom);
        }

        updateWindowDragBounds(nX, nY, mTmpRect);
        return false;
    }

    /**
     * The user is drag - resizing the window.
     *
     * @param x The x coordinate of the current drag coordinate.
     * @param y the y coordinate of the current drag coordinate.
     */
    @VisibleForTesting
    void resizeDrag(float x, float y) {
        // This is a resizing operation.
        // We need to keep various constraints:
        // 1. mMinVisible[Width/Height] <= [width/height] <= mMaxVisibleSize.[x/y]
        // 2. The orientation is kept - if required.
        final int deltaX = Math.round(x - mStartDragX);
        final int deltaY = Math.round(y - mStartDragY);
        int left = mWindowOriginalBounds.left;
        int top = mWindowOriginalBounds.top;
        int right = mWindowOriginalBounds.right;
        int bottom = mWindowOriginalBounds.bottom;

        // The aspect which we have to respect. Note that if the orientation does not need to be
        // preserved the aspect will be calculated as 1.0 which neutralizes the following
        // computations.
        final float minAspect = !mPreserveOrientation
                ? 1.0f
                : (mStartOrientationWasLandscape ? MIN_ASPECT : (1.0f / MIN_ASPECT));
        // Calculate the resulting width and height of the drag operation.
        int width = right - left;
        int height = bottom - top;
        if ((mCtrlType & CTRL_LEFT) != 0) {
            width = Math.max(mMinVisibleWidth, width - deltaX);
        } else if ((mCtrlType & CTRL_RIGHT) != 0) {
            width = Math.max(mMinVisibleWidth, width + deltaX);
        }
        if ((mCtrlType & CTRL_TOP) != 0) {
            height = Math.max(mMinVisibleHeight, height - deltaY);
        } else if ((mCtrlType & CTRL_BOTTOM) != 0) {
            height = Math.max(mMinVisibleHeight, height + deltaY);
        }

        // If we have to preserve the orientation - check that we are doing so.
        final float aspect = (float) width / (float) height;
        if (mPreserveOrientation && ((mStartOrientationWasLandscape && aspect < MIN_ASPECT)
                || (!mStartOrientationWasLandscape && aspect > (1.0 / MIN_ASPECT)))) {
            // Calculate 2 rectangles fulfilling all requirements for either X or Y being the major
            // drag axis. What ever is producing the bigger rectangle will be chosen.
            int width1;
            int width2;
            int height1;
            int height2;
            if (mStartOrientationWasLandscape) {
                // Assuming that the width is our target we calculate the height.
                width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
                height1 = Math.min(height, Math.round((float)width1 / MIN_ASPECT));
                if (height1 < mMinVisibleHeight) {
                    // If the resulting height is too small we adjust to the minimal size.
                    height1 = mMinVisibleHeight;
                    width1 = Math.max(mMinVisibleWidth,
                            Math.min(mMaxVisibleSize.x, Math.round((float)height1 * MIN_ASPECT)));
                }
                // Assuming that the height is our target we calculate the width.
                height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
                width2 = Math.max(width, Math.round((float)height2 * MIN_ASPECT));
                if (width2 < mMinVisibleWidth) {
                    // If the resulting width is too small we adjust to the minimal size.
                    width2 = mMinVisibleWidth;
                    height2 = Math.max(mMinVisibleHeight,
                            Math.min(mMaxVisibleSize.y, Math.round((float)width2 / MIN_ASPECT)));
                }
            } else {
                // Assuming that the width is our target we calculate the height.
                width1 = Math.max(mMinVisibleWidth, Math.min(mMaxVisibleSize.x, width));
                height1 = Math.max(height, Math.round((float)width1 * MIN_ASPECT));
                if (height1 < mMinVisibleHeight) {
                    // If the resulting height is too small we adjust to the minimal size.
                    height1 = mMinVisibleHeight;
                    width1 = Math.max(mMinVisibleWidth,
                            Math.min(mMaxVisibleSize.x, Math.round((float)height1 / MIN_ASPECT)));
                }
                // Assuming that the height is our target we calculate the width.
                height2 = Math.max(mMinVisibleHeight, Math.min(mMaxVisibleSize.y, height));
                width2 = Math.min(width, Math.round((float)height2 / MIN_ASPECT));
                if (width2 < mMinVisibleWidth) {
                    // If the resulting width is too small we adjust to the minimal size.
                    width2 = mMinVisibleWidth;
                    height2 = Math.max(mMinVisibleHeight,
                            Math.min(mMaxVisibleSize.y, Math.round((float)width2 * MIN_ASPECT)));
                }
            }

            // Use the bigger of the two rectangles if the major change was positive, otherwise
            // do the opposite.
            final boolean grows = width > (right - left) || height > (bottom - top);
            if (grows == (width1 * height1 > width2 * height2)) {
                width = width1;
                height = height1;
            } else {
                width = width2;
                height = height2;
            }
        }

        // Update mWindowDragBounds to the new drag size.
        updateDraggedBounds(left, top, right, bottom, width, height);
    }

    /**
     * Given the old coordinates and the new width and height, update the mWindowDragBounds.
     *
     * @param left      The original left bound before the user started dragging.
     * @param top       The original top bound before the user started dragging.
     * @param right     The original right bound before the user started dragging.
     * @param bottom    The original bottom bound before the user started dragging.
     * @param newWidth  The new dragged width.
     * @param newHeight The new dragged height.
     */
    void updateDraggedBounds(int left, int top, int right, int bottom, int newWidth,
                             int newHeight) {
        // Generate the final bounds by keeping the opposite drag edge constant.
        if ((mCtrlType & CTRL_LEFT) != 0) {
            left = right - newWidth;
        } else { // Note: The right might have changed - if we pulled at the right or not.
            right = left + newWidth;
        }
        if ((mCtrlType & CTRL_TOP) != 0) {
            top = bottom - newHeight;
        } else { // Note: The height might have changed - if we pulled at the bottom or not.
            bottom = top + newHeight;
        }

        mWindowDragBounds.set(left, top, right, bottom);

        checkBoundsForOrientationViolations(mWindowDragBounds);
    }

    /**
     * Validate bounds against orientation violations (if DEBUG_ORIENTATION_VIOLATIONS is set).
     *
     * @param bounds The bounds to be checked.
     */
    private void checkBoundsForOrientationViolations(Rect bounds) {
        // When using debug check that we are not violating the given constraints.
        if (DEBUG_ORIENTATION_VIOLATIONS) {
            if (mStartOrientationWasLandscape != (bounds.width() >= bounds.height())) {
                Slog.e(TAG, "Orientation violation detected! should be "
                        + (mStartOrientationWasLandscape ? "landscape" : "portrait")
                        + " but is the other");
            } else {
                Slog.v(TAG, "new bounds size: " + bounds.width() + " x " + bounds.height());
            }
            if (mMinVisibleWidth > bounds.width() || mMinVisibleHeight > bounds.height()) {
                Slog.v(TAG, "Minimum requirement violated: Width(min, is)=(" + mMinVisibleWidth
                        + ", " + bounds.width() + ") Height(min,is)=("
                        + mMinVisibleHeight + ", " + bounds.height() + ")");
            }
            if (mMaxVisibleSize.x < bounds.width() || mMaxVisibleSize.y < bounds.height()) {
                Slog.v(TAG, "Maximum requirement violated: Width(min, is)=(" + mMaxVisibleSize.x
                        + ", " + bounds.width() + ") Height(min,is)=("
                        + mMaxVisibleSize.y + ", " + bounds.height() + ")");
            }
        }
    }

    private void updateWindowDragBounds(int x, int y, Rect stackBounds) {
        final int offsetX = Math.round(x - mStartDragX);
        final int offsetY = Math.round(y - mStartDragY);
        mWindowDragBounds.set(mWindowOriginalBounds);
        // Horizontally, at least mMinVisibleWidth pixels of the window should remain visible.
        final int maxLeft = stackBounds.right - mMinVisibleWidth;
        final int minLeft = stackBounds.left + mMinVisibleWidth - mWindowOriginalBounds.width();

        // Vertically, the top mMinVisibleHeight of the window should remain visible.
        // (This assumes that the window caption bar is at the top of the window).
        final int minTop = stackBounds.top;
        final int maxTop = stackBounds.bottom - mMinVisibleHeight;

        mWindowDragBounds.offsetTo(
                Math.min(Math.max(mWindowOriginalBounds.left + offsetX, minLeft), maxLeft),
                Math.min(Math.max(mWindowOriginalBounds.top + offsetY, minTop), maxTop));

        if (DEBUG_TASK_POSITIONING) Slog.d(TAG,
                "updateWindowDragBounds: " + mWindowDragBounds);
    }

    public String toShortString() {
        return TAG;
    }

    static void setFactory(Factory factory) {
        sFactory = factory;
    }

    static TaskPositioner create(WindowManagerService service) {
        if (sFactory == null) {
            sFactory = new Factory() {};
        }

        return sFactory.create(service);
    }

    interface Factory {
        default TaskPositioner create(WindowManagerService service) {
            return new TaskPositioner(service);
        }
    }
}
