/*
 * 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.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.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
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.IActivityManager;
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
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.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerService.H;

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.mWindowMap) {
                            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.mWindowMap) {
                        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();
                    mTask.getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
                }
                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 display 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(null);
        mDragApplicationHandle.name = TAG;
        mDragApplicationHandle.dispatchingTimeoutNanos =
                WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;

        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
                display.getDisplayId());
        mDragWindowHandle.name = TAG;
        mDragWindowHandle.inputChannel = mServerChannel;
        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();

        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;

        // 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 dim bounds, not the original task bounds. The cursor
        // movement should be calculated relative to the visible bounds.
        // Also, use the dim 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.getDimBounds(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.mWindowMap) {
                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);
        }
    }
}
