/*
 * Copyright (C) 2012 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_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;

import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.server.wm.DockedStackDividerControllerProto.MINIMIZED_DOCK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.IDockedStackListener;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.WindowManagerService.H;

import java.io.PrintWriter;

/**
 * Keeps information about the docked stack divider.
 */
public class DockedStackDividerController {

    private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;

    /**
     * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
     * revealing surface at the earliest.
     */
    private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f;

    /**
     * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
     * revealing surface at the latest.
     */
    private static final float CLIP_REVEAL_MEET_LAST = 1f;

    /**
     * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start
     * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}.
     */
    private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f;

    /**
     * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance,
     * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}.
     */
    private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;

    private static final Interpolator IME_ADJUST_ENTRY_INTERPOLATOR =
            new PathInterpolator(0.2f, 0f, 0.1f, 1f);

    private static final long IME_ADJUST_ANIM_DURATION = 280;

    private static final long IME_ADJUST_DRAWN_TIMEOUT = 200;

    private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;

    private final WindowManagerService mService;
    private final DisplayContent mDisplayContent;
    private int mDividerWindowWidth;
    private int mDividerWindowWidthInactive;
    private int mDividerInsets;
    private int mTaskHeightInMinimizedMode;
    private boolean mResizing;
    private WindowState mWindow;
    private final Rect mTmpRect = new Rect();
    private final Rect mTmpRect2 = new Rect();
    private final Rect mTmpRect3 = new Rect();
    private final Rect mLastRect = new Rect();
    private boolean mLastVisibility = false;
    private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
            = new RemoteCallbackList<>();

    private boolean mMinimizedDock;
    private int mOriginalDockedSide = DOCKED_INVALID;
    private boolean mAnimatingForMinimizedDockedStack;
    private boolean mAnimationStarted;
    private long mAnimationStartTime;
    private float mAnimationStart;
    private float mAnimationTarget;
    private long mAnimationDuration;
    private boolean mAnimationStartDelayed;
    private final Interpolator mMinimizedDockInterpolator;
    private float mMaximizeMeetFraction;
    private final Rect mTouchRegion = new Rect();
    private boolean mAnimatingForIme;
    private boolean mAdjustedForIme;
    private int mImeHeight;
    private WindowState mDelayedImeWin;
    private boolean mAdjustedForDivider;
    private float mDividerAnimationStart;
    private float mDividerAnimationTarget;
    float mLastAnimationProgress;
    float mLastDividerProgress;
    private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
    private boolean mImeHideRequested;
    private ActivityStack mDimmedStack;

    DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
        mService = service;
        mDisplayContent = displayContent;
        final Context context = service.mContext;
        mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
                context, android.R.interpolator.fast_out_slow_in);
        loadDimens();
    }

    int getSmallestWidthDpForBounds(Rect bounds) {
        final DisplayInfo di = mDisplayContent.getDisplayInfo();

        final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
        final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
        int minWidth = Integer.MAX_VALUE;

        // Go through all screen orientations and find the orientation in which the task has the
        // smallest width.
        for (int rotation = 0; rotation < 4; rotation++) {
            mTmpRect.set(bounds);
            mDisplayContent.rotateBounds(di.rotation, rotation, mTmpRect);
            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
            mTmpRect2.set(0, 0,
                    rotated ? baseDisplayHeight : baseDisplayWidth,
                    rotated ? baseDisplayWidth : baseDisplayHeight);
            final int orientation = mTmpRect2.width() <= mTmpRect2.height()
                    ? ORIENTATION_PORTRAIT
                    : ORIENTATION_LANDSCAPE;
            final int dockSide = getDockSide(mTmpRect, mTmpRect2, orientation, rotation);
            final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
                    getContentWidth());

            final DisplayCutout displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(
                    rotation).getDisplayCutout();

            // Since we only care about feasible states, snap to the closest snap target, like it
            // would happen when actually rotating the screen.
            final int snappedPosition = mSnapAlgorithmForRotation[rotation]
                    .calculateNonDismissingSnapTarget(position).position;
            DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect,
                    mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
            mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, mTmpRect2.width(),
                    mTmpRect2.height(), displayCutout, mTmpRect3);
            mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
            minWidth = Math.min(mTmpRect.width(), minWidth);
        }
        return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
    }

    /**
     * Get the current docked side. Determined by its location of {@param bounds} within
     * {@param displayRect} but if both are the same, it will try to dock to each side and determine
     * if allowed in its respected {@param orientation}.
     *
     * @param bounds bounds of the docked task to get which side is docked
     * @param displayRect bounds of the display that contains the docked task
     * @param orientation the origination of device
     * @return current docked side
     */
    int getDockSide(Rect bounds, Rect displayRect, int orientation, int rotation) {
        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            // Portrait mode, docked either at the top or the bottom.
            final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
            if (diff > 0) {
                return DOCKED_TOP;
            } else if (diff < 0) {
                return DOCKED_BOTTOM;
            }
            return canPrimaryStackDockTo(DOCKED_TOP, displayRect, rotation)
                    ? DOCKED_TOP : DOCKED_BOTTOM;
        } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // Landscape mode, docked either on the left or on the right.
            final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
            if (diff > 0) {
                return DOCKED_LEFT;
            } else if (diff < 0) {
                return DOCKED_RIGHT;
            }
            return canPrimaryStackDockTo(DOCKED_LEFT, displayRect, rotation)
                    ? DOCKED_LEFT : DOCKED_RIGHT;
        }
        return DOCKED_INVALID;
    }

    void getHomeStackBoundsInDockedMode(Configuration parentConfig, int dockSide, Rect outBounds) {
        final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout;
        final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
        final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
        mDisplayContent.getDisplayPolicy().getStableInsetsLw(
                parentConfig.windowConfiguration.getRotation(), displayWidth, displayHeight,
                displayCutout, mTmpRect);
        int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
        // The offset in the left (landscape)/top (portrait) is calculated with the minimized
        // offset value with the divider size and any system insets in that direction.
        if (parentConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            outBounds.set(0, mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top,
                    displayWidth, displayHeight);
        } else {
            // In landscape also inset the left/right side with the status bar height to match the
            // minimized size height in portrait mode.
            final int primaryTaskWidth = mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top;
            int left = mTmpRect.left;
            int right = displayWidth - mTmpRect.right;
            if (dockSide == DOCKED_LEFT) {
                left += primaryTaskWidth;
            } else if (dockSide == DOCKED_RIGHT) {
                right -= primaryTaskWidth;
            }
            outBounds.set(left, 0, right, displayHeight);
        }
    }

    boolean isHomeStackResizable() {
        final ActivityStack homeStack = mDisplayContent.getHomeStack();
        if (homeStack == null) {
            return false;
        }
        final Task homeTask = homeStack.getTopMostTask();
        return homeTask != null && homeTask.isResizeable();
    }

    private void initSnapAlgorithmForRotations() {
        final Configuration baseConfig = mDisplayContent.getConfiguration();

        // Initialize the snap algorithms for all 4 screen orientations.
        final Configuration config = new Configuration();
        for (int rotation = 0; rotation < 4; rotation++) {
            final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
            final int dw = rotated
                    ? mDisplayContent.mBaseDisplayHeight
                    : mDisplayContent.mBaseDisplayWidth;
            final int dh = rotated
                    ? mDisplayContent.mBaseDisplayWidth
                    : mDisplayContent.mBaseDisplayHeight;
            final DisplayCutout displayCutout =
                    mDisplayContent.calculateDisplayCutoutForRotation(rotation).getDisplayCutout();
            final DisplayPolicy displayPolicy =  mDisplayContent.getDisplayPolicy();
            displayPolicy.getStableInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);
            config.unset();
            config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;

            final int appWidth = displayPolicy.getNonDecorDisplayWidth(dw, dh, rotation,
                    baseConfig.uiMode, displayCutout);
            final int appHeight = displayPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
                    baseConfig.uiMode, displayCutout);
            displayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);
            final int leftInset = mTmpRect.left;
            final int topInset = mTmpRect.top;

            config.windowConfiguration.setAppBounds(leftInset /*left*/, topInset /*top*/,
                    leftInset + appWidth /*right*/, topInset + appHeight /*bottom*/);

            final float density = mDisplayContent.getDisplayMetrics().density;
            config.screenWidthDp = (int) (displayPolicy.getConfigDisplayWidth(dw, dh, rotation,
                    baseConfig.uiMode, displayCutout) / density);
            config.screenHeightDp = (int) (displayPolicy.getConfigDisplayHeight(dw, dh, rotation,
                    baseConfig.uiMode, displayCutout) / density);
            final Context rotationContext = mService.mContext.createConfigurationContext(config);
            mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
                    rotationContext.getResources(), dw, dh, getContentWidth(),
                    config.orientation == ORIENTATION_PORTRAIT, mTmpRect);
        }
    }

    private void loadDimens() {
        final Context context = mService.mContext;
        mDividerWindowWidth = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.docked_stack_divider_thickness);
        mDividerInsets = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.docked_stack_divider_insets);
        mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
                DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
        mTaskHeightInMinimizedMode = context.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.task_height_of_minimized_mode);
        initSnapAlgorithmForRotations();
    }

    void onConfigurationChanged() {
        loadDimens();
    }

    boolean isResizing() {
        return mResizing;
    }

    int getContentWidth() {
        return mDividerWindowWidth - 2 * mDividerInsets;
    }

    int getContentInsets() {
        return mDividerInsets;
    }

    int getContentWidthInactive() {
        return mDividerWindowWidthInactive;
    }

    void setResizing(boolean resizing) {
        if (mResizing != resizing) {
            mResizing = resizing;
            resetDragResizingChangeReported();
        }
    }

    void setTouchRegion(Rect touchRegion) {
        mTouchRegion.set(touchRegion);
    }

    void getTouchRegion(Rect outRegion) {
        outRegion.set(mTouchRegion);
        if (mWindow != null) {
            outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
        }
    }

    private void resetDragResizingChangeReported() {
        mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported,
                true /* traverseTopToBottom */ );
    }

    void setWindow(WindowState window) {
        mWindow = window;
        reevaluateVisibility(false);
    }

    void reevaluateVisibility(boolean force) {
        if (mWindow == null) {
            return;
        }
        ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();

        // If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
        final boolean visible = stack != null;
        if (mLastVisibility == visible && !force) {
            return;
        }
        mLastVisibility = visible;
        notifyDockedDividerVisibilityChanged(visible);
        if (!visible) {
            setResizeDimLayer(false, WINDOWING_MODE_UNDEFINED, 0f);
        }
    }

    private boolean wasVisible() {
        return mLastVisibility;
    }

    void setAdjustedForIme(
            boolean adjustedForIme, boolean adjustedForDivider,
            boolean animate, WindowState imeWin, int imeHeight) {
        if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight)
                || mAdjustedForDivider != adjustedForDivider) {
            if (animate && !mAnimatingForMinimizedDockedStack) {
                // Notify SystemUI to set the target docked stack size according current docked
                // state without animation when calling startImeAdjustAnimation.
                notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */,
                        isHomeStackResizable());
                startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
            } else {
                // Animation might be delayed, so only notify if we don't run an animation.
                notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */);
            }
            mAdjustedForIme = adjustedForIme;
            mImeHeight = imeHeight;
            mAdjustedForDivider = adjustedForDivider;
        }
    }

    int getImeHeightAdjustedFor() {
        return mImeHeight;
    }

    void positionDockedStackedDivider(Rect frame) {
        ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
        if (stack == null) {
            // Unfortunately we might end up with still having a divider, even though the underlying
            // stack was already removed. This is because we are on AM thread and the removal of the
            // divider was deferred to WM thread and hasn't happened yet. In that case let's just
            // keep putting it in the same place it was before the stack was removed to have
            // continuity and prevent it from jumping to the center. It will get hidden soon.
            frame.set(mLastRect);
            return;
        } else {
            stack.getDimBounds(mTmpRect);
        }
        int side = stack.getDockSide();
        switch (side) {
            case DOCKED_LEFT:
                frame.set(mTmpRect.right - mDividerInsets, frame.top,
                        mTmpRect.right + frame.width() - mDividerInsets, frame.bottom);
                break;
            case DOCKED_TOP:
                frame.set(frame.left, mTmpRect.bottom - mDividerInsets,
                        mTmpRect.right, mTmpRect.bottom + frame.height() - mDividerInsets);
                break;
            case DOCKED_RIGHT:
                frame.set(mTmpRect.left - frame.width() + mDividerInsets, frame.top,
                        mTmpRect.left + mDividerInsets, frame.bottom);
                break;
            case DOCKED_BOTTOM:
                frame.set(frame.left, mTmpRect.top - frame.height() + mDividerInsets,
                        frame.right, mTmpRect.top + mDividerInsets);
                break;
        }
        mLastRect.set(frame);
    }

    private void notifyDockedDividerVisibilityChanged(boolean visible) {
        final int size = mDockedStackListeners.beginBroadcast();
        for (int i = 0; i < size; ++i) {
            final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
            try {
                listener.onDividerVisibilityChanged(visible);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering divider visibility changed event.", e);
            }
        }
        mDockedStackListeners.finishBroadcast();
    }

    /**
     * Checks if the primary stack is allowed to dock to a specific side based on its original dock
     * side.
     *
     * @param dockSide the side to see if it is valid
     * @return true if the side provided is valid
     */
    boolean canPrimaryStackDockTo(int dockSide, Rect parentRect, int rotation) {
        final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
        return isDockSideAllowed(dockSide, mOriginalDockedSide,
                policy.navigationBarPosition(parentRect.width(), parentRect.height(), rotation),
                policy.navigationBarCanMove());
    }

    @VisibleForTesting
    static boolean isDockSideAllowed(int dockSide, int originalDockSide, int navBarPosition,
            boolean navigationBarCanMove) {
        if (dockSide == DOCKED_TOP) {
            return true;
        }

        if (navigationBarCanMove) {
            // Only allow the dockside opposite to the nav bar position in landscape
            return dockSide == DOCKED_LEFT && navBarPosition == NAV_BAR_RIGHT
                    || dockSide == DOCKED_RIGHT && navBarPosition == NAV_BAR_LEFT;
        }

        // Side is the same as original side
        if (dockSide == originalDockSide) {
            return true;
        }

        // Only if original docked side was top in portrait will allow left for landscape
        return dockSide == DOCKED_LEFT && originalDockSide == DOCKED_TOP;
    }

    void notifyDockedStackExistsChanged(boolean exists) {
        // TODO(multi-display): Perform all actions only for current display.
        final int size = mDockedStackListeners.beginBroadcast();
        for (int i = 0; i < size; ++i) {
            final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
            try {
                listener.onDockedStackExistsChanged(exists);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering docked stack exists changed event.", e);
            }
        }
        mDockedStackListeners.finishBroadcast();
        if (exists) {
            InputMethodManagerInternal inputMethodManagerInternal =
                    LocalServices.getService(InputMethodManagerInternal.class);
            if (inputMethodManagerInternal != null) {

                // Hide the current IME to avoid problems with animations from IME adjustment when
                // attaching the docked stack.
                inputMethodManagerInternal.hideCurrentInputMethod();
                mImeHideRequested = true;
            }

            // If a primary stack was just created, it will not have access to display content at
            // this point so pass it from here to get a valid dock side.
            final ActivityStack stack =
                    mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
            mOriginalDockedSide = stack.getDockSideForDisplay(mDisplayContent);
            return;
        }
        mOriginalDockedSide = DOCKED_INVALID;
        setMinimizedDockedStack(false /* minimizedDock */, false /* animate */);

        if (mDimmedStack != null) {
            mDimmedStack.stopDimming();
            mDimmedStack = null;
        }
    }

    /**
     * Resets the state that IME hide has been requested. See {@link #isImeHideRequested}.
     */
    void resetImeHideRequested() {
        mImeHideRequested = false;
    }

    /**
     * The docked stack divider controller makes sure the IME gets hidden when attaching the docked
     * stack, to avoid animation problems. This flag indicates whether the request to hide the IME
     * has been sent in an asynchronous manner, and the IME should be treated as hidden already.
     *
     * @return whether IME hide request has been sent
     */
    boolean isImeHideRequested() {
        return mImeHideRequested;
    }

    private void notifyDockedStackMinimizedChanged(boolean minimizedDock, boolean animate,
            boolean isHomeStackResizable) {
        long animDuration = 0;
        if (animate) {
            final ActivityStack stack =
                    mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
            final long transitionDuration = isAnimationMaximizing()
                    ? mDisplayContent.mAppTransition.getLastClipRevealTransitionDuration()
                    : DEFAULT_APP_TRANSITION_DURATION;
            mAnimationDuration = (long)
                    (transitionDuration * mService.getTransitionAnimationScaleLocked());
            mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
            animDuration = (long) (mAnimationDuration * mMaximizeMeetFraction);
        }
        final int size = mDockedStackListeners.beginBroadcast();
        for (int i = 0; i < size; ++i) {
            final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
            try {
                listener.onDockedStackMinimizedChanged(minimizedDock, animDuration,
                        isHomeStackResizable);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e);
            }
        }
        mDockedStackListeners.finishBroadcast();
        // Only notify ATM after we update the remote listeners, otherwise it may trigger another
        // minimize change, which would lead to an inversion of states send to the listeners
        mService.mAtmInternal.notifyDockedStackMinimizedChanged(minimizedDock);
    }

    void notifyDockSideChanged(int newDockSide) {
        final int size = mDockedStackListeners.beginBroadcast();
        for (int i = 0; i < size; ++i) {
            final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
            try {
                listener.onDockSideChanged(newDockSide);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering dock side changed event.", e);
            }
        }
        mDockedStackListeners.finishBroadcast();
    }

    private void notifyAdjustedForImeChanged(boolean adjustedForIme, long animDuration) {
        final int size = mDockedStackListeners.beginBroadcast();
        for (int i = 0; i < size; ++i) {
            final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
            try {
                listener.onAdjustedForImeChanged(adjustedForIme, animDuration);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering adjusted for ime changed event.", e);
            }
        }
        mDockedStackListeners.finishBroadcast();
    }

    void registerDockedStackListener(IDockedStackListener listener) {
        mDockedStackListeners.register(listener);
        notifyDockedDividerVisibilityChanged(wasVisible());
        notifyDockedStackExistsChanged(
                mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null);
        notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */,
                isHomeStackResizable());
        notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);

    }

    /**
     * Shows a dim layer with {@param alpha} if {@param visible} is true and
     * {@param targetWindowingMode} isn't
     * {@link android.app.WindowConfiguration#WINDOWING_MODE_UNDEFINED} and there is a stack on the
     * display in that windowing mode.
     */
    void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
        // TODO: Maybe only allow split-screen windowing modes?
        final ActivityStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED
                ? mDisplayContent.getTopStackInWindowingMode(targetWindowingMode)
                : null;
        final ActivityStack dockedStack = mDisplayContent.getSplitScreenPrimaryStack();
        boolean visibleAndValid = visible && stack != null && dockedStack != null;

        // Ensure an old dim that was shown for the docked stack divider is removed so we don't end
        // up with dim layers that can no longer be removed.
        if (mDimmedStack != null && mDimmedStack != stack) {
            mDimmedStack.stopDimming();
            mDimmedStack = null;
        }

        if (visibleAndValid) {
            mDimmedStack = stack;
            stack.dim(alpha);
        }
        if (!visibleAndValid && stack != null) {
            mDimmedStack = null;
            stack.stopDimming();
        }
    }

    /**
     * Notifies the docked stack divider controller of a visibility change that happens without
     * an animation.
     */
    void notifyAppVisibilityChanged() {
        checkMinimizeChanged(false /* animate */);
    }

    void notifyAppTransitionStarting(ArraySet<ActivityRecord> openingApps, int appTransition) {
        final boolean wasMinimized = mMinimizedDock;
        checkMinimizeChanged(true /* animate */);

        // We were minimized, and now we are still minimized, but somebody is trying to launch an
        // app in docked stack, better show recent apps so we actually get unminimized! However do
        // not do this if keyguard is dismissed such as when the device is unlocking. This catches
        // any case that was missed in ActivityStarter.postStartActivityUncheckedProcessing because
        // we couldn't retrace the launch of the app in the docked stack to the launch from
        // homescreen.
        if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps)
                && appTransition != TRANSIT_NONE &&
                !AppTransition.isKeyguardGoingAwayTransit(appTransition)) {
            if (mService.mAtmInternal.isRecentsComponentHomeActivity(mService.mCurrentUserId)) {
                // When the home activity is the recents component and we are already minimized,
                // then there is nothing to do here since home is already visible
            } else {
                mService.showRecentApps();
            }
        }
    }

    /**
     * @return true if {@param apps} contains an activity in the docked stack, false otherwise.
     */
    private boolean containsAppInDockedStack(ArraySet<ActivityRecord> apps) {
        for (int i = apps.size() - 1; i >= 0; i--) {
            final ActivityRecord activity = apps.valueAt(i);
            if (activity.getTask() != null && activity.inSplitScreenPrimaryWindowingMode()) {
                return true;
            }
        }
        return false;
    }

    boolean isMinimizedDock() {
        return mMinimizedDock;
    }

    void checkMinimizeChanged(boolean animate) {
        if (mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() == null) {
            return;
        }
        final ActivityStack homeStack = mDisplayContent.getHomeStack();
        if (homeStack == null) {
            return;
        }
        final Task homeTask = homeStack.getTopMostTask();
        if (homeTask == null || !isWithinDisplay(homeTask)) {
            return;
        }

        // Do not minimize when dock is already minimized while keyguard is showing and not
        // occluded such as unlocking the screen
        if (mMinimizedDock && mService.mKeyguardOrAodShowingOnDefaultDisplay) {
            return;
        }
        final ActivityStack topSecondaryStack = mDisplayContent.getTopStackInWindowingMode(
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
        final boolean minimizedForRecentsAnimation = recentsAnim != null &&
                recentsAnim.isSplitScreenMinimized();
        boolean homeVisible = homeTask.getTopVisibleActivity() != null;
        if (homeVisible && topSecondaryStack != null) {
            // Home should only be considered visible if it is greater or equal to the top secondary
            // stack in terms of z-order.
            homeVisible = homeStack.compareTo(topSecondaryStack) >= 0;
        }
        setMinimizedDockedStack(homeVisible || minimizedForRecentsAnimation, animate);
    }

    private boolean isWithinDisplay(Task task) {
        task.getBounds(mTmpRect);
        mDisplayContent.getBounds(mTmpRect2);
        return mTmpRect.intersect(mTmpRect2);
    }

    /**
     * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the
     * docked stack are heavily clipped so you can only see a minimal peek state.
     *
     * @param minimizedDock Whether the docked stack is currently minimized.
     * @param animate Whether to animate the change.
     */
    private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
        final boolean wasMinimized = mMinimizedDock;
        mMinimizedDock = minimizedDock;
        if (minimizedDock == wasMinimized) {
            return;
        }

        final boolean imeChanged = clearImeAdjustAnimation();
        boolean minimizedChange = false;
        if (isHomeStackResizable()) {
            notifyDockedStackMinimizedChanged(minimizedDock, animate,
                    true /* isHomeStackResizable */);
            minimizedChange = true;
        } else {
            if (minimizedDock) {
                if (animate) {
                    startAdjustAnimation(0f, 1f);
                } else {
                    minimizedChange |= setMinimizedDockedStack(true);
                }
            } else {
                if (animate) {
                    startAdjustAnimation(1f, 0f);
                } else {
                    minimizedChange |= setMinimizedDockedStack(false);
                }
            }
        }
        if (imeChanged || minimizedChange) {
            if (imeChanged && !minimizedChange) {
                Slog.d(TAG, "setMinimizedDockedStack: IME adjust changed due to minimizing,"
                        + " minimizedDock=" + minimizedDock
                        + " minimizedChange=" + minimizedChange);
            }
            mService.mWindowPlacerLocked.performSurfacePlacement();
        }
    }

    private boolean clearImeAdjustAnimation() {
        final boolean changed = mDisplayContent.clearImeAdjustAnimation();
        mAnimatingForIme = false;
        return changed;
    }

    private void startAdjustAnimation(float from, float to) {
        mAnimatingForMinimizedDockedStack = true;
        mAnimationStarted = false;
        mAnimationStart = from;
        mAnimationTarget = to;
    }

    private void startImeAdjustAnimation(
            boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) {

        // If we're not in an animation, the starting point depends on whether we're adjusted
        // or not. If we're already in an animation, we start from where the current animation
        // left off, so that the motion doesn't look discontinuous.
        if (!mAnimatingForIme) {
            mAnimationStart = mAdjustedForIme ? 1 : 0;
            mDividerAnimationStart = mAdjustedForDivider ? 1 : 0;
            mLastAnimationProgress = mAnimationStart;
            mLastDividerProgress = mDividerAnimationStart;
        } else {
            mAnimationStart = mLastAnimationProgress;
            mDividerAnimationStart = mLastDividerProgress;
        }
        mAnimatingForIme = true;
        mAnimationStarted = false;
        mAnimationTarget = adjustedForIme ? 1 : 0;
        mDividerAnimationTarget = adjustedForDivider ? 1 : 0;

        mDisplayContent.beginImeAdjustAnimation();

        // We put all tasks into drag resizing mode - wait until all of them have completed the
        // drag resizing switch.
        final Runnable existingWaitingForDrwanCallback =
                mService.mWaitingForDrawnCallbacks.get(mService.mRoot);
        if (existingWaitingForDrwanCallback != null) {
            mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, mService.mRoot);
            mService.mH.sendMessageDelayed(mService.mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT,
                    mService.mRoot),
                    IME_ADJUST_DRAWN_TIMEOUT);
            mAnimationStartDelayed = true;
            if (imeWin != null) {

                // There might be an old window delaying the animation start - clear it.
                if (mDelayedImeWin != null) {
                    mDelayedImeWin.endDelayingAnimationStart();
                }
                mDelayedImeWin = imeWin;
                imeWin.startDelayingAnimationStart();
            }

            // If we are already waiting for something to be drawn, clear out the old one so it
            // still gets executed.
            // TODO: Have a real system where we can wait on different windows to be drawn with
            // different callbacks.
            existingWaitingForDrwanCallback.run();
            mService.mWaitingForDrawnCallbacks.put(mService.mRoot, () -> {
                synchronized (mService.mGlobalLock) {
                    mAnimationStartDelayed = false;
                    if (mDelayedImeWin != null) {
                        mDelayedImeWin.endDelayingAnimationStart();
                    }
                    // If the adjust status changed since this was posted, only notify
                    // the new states and don't animate.
                    long duration = 0;
                    if (mAdjustedForIme == adjustedForIme
                            && mAdjustedForDivider == adjustedForDivider) {
                        duration = IME_ADJUST_ANIM_DURATION;
                    } else {
                        Slog.w(TAG, "IME adjust changed while waiting for drawn:"
                                + " adjustedForIme=" + adjustedForIme
                                + " adjustedForDivider=" + adjustedForDivider
                                + " mAdjustedForIme=" + mAdjustedForIme
                                + " mAdjustedForDivider=" + mAdjustedForDivider);
                    }
                    notifyAdjustedForImeChanged(
                            mAdjustedForIme || mAdjustedForDivider, duration);
                }
            });
        } else {
            notifyAdjustedForImeChanged(
                    adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
        }
    }

    private boolean setMinimizedDockedStack(boolean minimized) {
        final ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
        notifyDockedStackMinimizedChanged(minimized, false /* animate */, isHomeStackResizable());
        return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
    }

    private boolean isAnimationMaximizing() {
        return mAnimationTarget == 0f;
    }

    public boolean animate(long now) {
        if (mWindow == null) {
            return false;
        }
        if (mAnimatingForMinimizedDockedStack) {
            return animateForMinimizedDockedStack(now);
        } else if (mAnimatingForIme && !mDisplayContent.mAppTransition.isRunning()) {
            // To prevent task stack resize animation may flicking when playing app transition
            // animation & IME window enter animation in parallel, make sure app transition is done
            // and then start to animate for IME.
            return animateForIme(now);
        }
        return false;
    }

    private boolean animateForIme(long now) {
        if (!mAnimationStarted || mAnimationStartDelayed) {
            mAnimationStarted = true;
            mAnimationStartTime = now;
            mAnimationDuration = (long)
                    (IME_ADJUST_ANIM_DURATION * mService.getWindowAnimationScaleLocked());
        }
        float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
        t = (mAnimationTarget == 1f ? IME_ADJUST_ENTRY_INTERPOLATOR : TOUCH_RESPONSE_INTERPOLATOR)
                .getInterpolation(t);
        final boolean updated =
                mDisplayContent.animateForIme(t, mAnimationTarget, mDividerAnimationTarget);
        if (updated) {
            mService.mWindowPlacerLocked.performSurfacePlacement();
        }
        if (t >= 1.0f) {
            mLastAnimationProgress = mAnimationTarget;
            mLastDividerProgress = mDividerAnimationTarget;
            mAnimatingForIme = false;
            return false;
        } else {
            return true;
        }
    }

    private boolean animateForMinimizedDockedStack(long now) {
        final ActivityStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
        if (!mAnimationStarted) {
            mAnimationStarted = true;
            mAnimationStartTime = now;
            notifyDockedStackMinimizedChanged(mMinimizedDock, true /* animate */,
                    isHomeStackResizable() /* isHomeStackResizable */);
        }
        float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
        t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
                .getInterpolation(t);
        if (stack != null) {
            if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) {
                mService.mWindowPlacerLocked.performSurfacePlacement();
            }
        }
        if (t >= 1.0f) {
            mAnimatingForMinimizedDockedStack = false;
            return false;
        } else {
            return true;
        }
    }

    float getInterpolatedAnimationValue(float t) {
        return t * mAnimationTarget + (1 - t) * mAnimationStart;
    }

    float getInterpolatedDividerValue(float t) {
        return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart;
    }

    /**
     * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
     */
    private float getMinimizeAmount(ActivityStack stack, float t) {
        final float naturalAmount = getInterpolatedAnimationValue(t);
        if (isAnimationMaximizing()) {
            return adjustMaximizeAmount(stack, t, naturalAmount);
        } else {
            return naturalAmount;
        }
    }

    /**
     * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount
     * during the transition such that the edge of the clip reveal rect is met earlier in the
     * transition so we don't create a visible "hole", but only if both the clip reveal and the
     * docked stack divider start from about the same portion on the screen.
     */
    private float adjustMaximizeAmount(ActivityStack stack, float t, float naturalAmount) {
        if (mMaximizeMeetFraction == 1f) {
            return naturalAmount;
        }
        final int minimizeDistance = stack.getMinimizeDistance();
        final float startPrime = mDisplayContent.mAppTransition.getLastClipRevealMaxTranslation()
                / (float) minimizeDistance;
        final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime;
        final float t2 = Math.min(t / mMaximizeMeetFraction, 1);
        return amountPrime * t2 + naturalAmount * (1 - t2);
    }

    /**
     * Retrieves the animation fraction at which the docked stack has to meet the clip reveal
     * edge. See {@link #adjustMaximizeAmount}.
     */
    private float getClipRevealMeetFraction(ActivityStack stack) {
        if (!isAnimationMaximizing() || stack == null ||
                !mDisplayContent.mAppTransition.hadClipRevealAnimation()) {
            return 1f;
        }
        final int minimizeDistance = stack.getMinimizeDistance();
        final float fraction = Math.abs(mDisplayContent.mAppTransition
                .getLastClipRevealMaxTranslation()) / (float) minimizeDistance;
        final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN)
                / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN)));
        return CLIP_REVEAL_MEET_EARLIEST
                + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
    }

    public String toShortString() {
        return TAG;
    }

    WindowState getWindow() {
        return mWindow;
    }

    void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + "DockedStackDividerController");
        pw.println(prefix + "  mLastVisibility=" + mLastVisibility);
        pw.println(prefix + "  mMinimizedDock=" + mMinimizedDock);
        pw.println(prefix + "  mAdjustedForIme=" + mAdjustedForIme);
        pw.println(prefix + "  mAdjustedForDivider=" + mAdjustedForDivider);
    }

    void dumpDebug(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        proto.write(MINIMIZED_DOCK, mMinimizedDock);
        proto.end(token);
    }
}
