Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff71d20f authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Put windows into resizing during IME adjust animation

Because the IME animates in with translucency there was a black hole
visible at the bottom. This CL puts the window into resizing mode,
waits until the change is commited, and then starts the animation

Bug: 28175599
Change-Id: Ib31c1e765639e5490208bccba77b25318ec8dc71
parent 698e7634
Loading
Loading
Loading
Loading
+57 −9
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
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.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

@@ -41,6 +42,7 @@ import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;

import com.android.server.wm.DimLayer.DimLayerUser;
import com.android.server.wm.WindowManagerService.H;

import java.util.ArrayList;

@@ -76,10 +78,12 @@ public class DockedStackDividerController implements DimLayerUser {
    private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;

    private static final Interpolator IME_ADJUST_ENTRY_INTERPOLATOR =
            new PathInterpolator(0.1f, 0f, 0.1f, 1f);
            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 final WindowManagerService mService;
    private final DisplayContent mDisplayContent;
    private int mDividerWindowWidth;
@@ -101,11 +105,13 @@ public class DockedStackDividerController implements DimLayerUser {
    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 WindowState mDelayedImeWin;

    DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
        mService = service;
@@ -192,13 +198,16 @@ public class DockedStackDividerController implements DimLayerUser {
        return mLastVisibility;
    }

    void setAdjustedForIme(boolean adjusted, boolean animate) {
    void setAdjustedForIme(boolean adjusted, boolean animate, WindowState imeWin) {
        if (mAdjustedForIme != adjusted) {
            mAdjustedForIme = adjusted;
            if (animate) {
                startImeAdjustAnimation(adjusted ? 0 : 1, adjusted ? 1 : 0);
                startImeAdjustAnimation(adjusted, imeWin);
            } else {

                // Animation might be delayed, so only notify if we don't run an animation.
                notifyAdjustedForImeChanged(adjusted, 0 /* duration */);
            }
            notifyAdjustedForImeChanged(adjusted, animate ? IME_ADJUST_ANIM_DURATION : 0);
        }
    }

@@ -429,11 +438,46 @@ public class DockedStackDividerController implements DimLayerUser {
        mAnimationTarget = to;
    }

    private void startImeAdjustAnimation(float from, float to) {
    private void startImeAdjustAnimation(boolean adjusted, WindowState imeWin) {
        mAnimatingForIme = true;
        mAnimationStarted = false;
        mAnimationStart = from;
        mAnimationTarget = to;
        mAnimationStart = adjusted ? 0 : 1;
        mAnimationTarget = adjusted ? 1 : 0;

        final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
        for (int i = stacks.size() - 1; i >= 0; --i) {
            final TaskStack stack = stacks.get(i);
            if (stack.isVisibleLocked() && stack.isAdjustedForIme()) {
                stack.beginImeAdjustAnimation();
            }
        }

        // We put all tasks into drag resizing mode - wait until all of them have completed the
        // drag resizing switch.
        if (!mService.mWaitingForDrawn.isEmpty()) {
            mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
            mService.mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT,
                    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.mWinAnimator.endDelayingAnimationStart();
                }
                mDelayedImeWin = imeWin;
                imeWin.mWinAnimator.startDelayingAnimationStart();
            }
            mService.mWaitingForDrawnCallback = () -> {
                mAnimationStartDelayed = false;
                if (mDelayedImeWin != null) {
                    mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
                }
                notifyAdjustedForImeChanged(adjusted, IME_ADJUST_ANIM_DURATION);
            };
        } else {
            notifyAdjustedForImeChanged(adjusted, IME_ADJUST_ANIM_DURATION);
        }
    }

    private void setMinimizedDockedStack(boolean minimized) {
@@ -462,7 +506,7 @@ public class DockedStackDividerController implements DimLayerUser {
    }

    private boolean animateForIme(long now) {
        if (!mAnimationStarted) {
        if (!mAnimationStarted || mAnimationStartDelayed) {
            mAnimationStarted = true;
            mAnimationStartTime = now;
            mAnimationDuration = (long)
@@ -480,7 +524,11 @@ public class DockedStackDividerController implements DimLayerUser {
                    stack.resetAdjustedForIme(true /* adjustBoundsNow */);
                    updated = true;
                } else {
                    updated |= stack.updateAdjustForIme(getInterpolatedAnimationValue(t));
                    updated |= stack.updateAdjustForIme(getInterpolatedAnimationValue(t),
                            false /* force */);
                }
                if (t >= 1f) {
                    stack.endImeAdjustAnimation();
                }
            }
        }
+26 −0
Original line number Diff line number Diff line
@@ -509,6 +509,22 @@ class Task implements DimLayer.DimLayerUser {
        return mDragResizeMode;
    }

    /**
     * Adds all of the tasks windows to {@link WindowManagerService#mWaitingForDrawn} if drag
     * resizing state of the window has been changed.
     */
    void addWindowsWaitingForDrawnIfResizingChanged() {
        for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
            final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                final WindowState win = windows.get(winNdx);
                if (win.isDragResizeChanged()) {
                    mService.mWaitingForDrawn.add(win);
                }
            }
        }
    }

    void updateDisplayInfo(final DisplayContent displayContent) {
        if (displayContent == null) {
            return;
@@ -619,6 +635,16 @@ class Task implements DimLayer.DimLayerUser {
        return false;
    }

    boolean isVisible() {
        for (int i = mAppTokens.size() - 1; i >= 0; i--) {
            final AppWindowToken appToken = mAppTokens.get(i);
            if (appToken.isVisible()) {
                return true;
            }
        }
        return false;
    }

    boolean inHomeStack() {
        return mStack != null && mStack.mStackId == HOME_STACK_ID;
    }
+32 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ 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 com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
@@ -833,10 +834,13 @@ public class TaskStack implements DimLayer.DimLayerUser,
     * @param imeWin The IME window.
     */
    void setAdjustedForIme(WindowState imeWin) {
        mAdjustedForIme = true;
        mAdjustImeAmount = 0f;
        mImeWin = imeWin;
        mImeGoingAway = false;
        if (!mAdjustedForIme) {
            mAdjustedForIme = true;
            mAdjustImeAmount = 0f;
            updateAdjustForIme(0f, true /* force */);
        }
    }

    boolean isAdjustedForIme() {
@@ -855,8 +859,8 @@ public class TaskStack implements DimLayer.DimLayerUser,
     *
     * @return true if a traversal should be performed after the adjustment.
     */
    boolean updateAdjustForIme(float adjustAmount) {
        if (adjustAmount != mAdjustImeAmount) {
    boolean updateAdjustForIme(float adjustAmount, boolean force) {
        if (adjustAmount != mAdjustImeAmount || force) {
            mAdjustImeAmount = adjustAmount;
            updateAdjustedBounds();
            return isVisibleForUserLocked();
@@ -903,6 +907,29 @@ public class TaskStack implements DimLayer.DimLayerUser,
        return mMinimizeAmount != 0f;
    }

    /**
     * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
     * to the list of to be drawn windows the service is waiting for.
     */
    void beginImeAdjustAnimation() {
        for (int j = mTasks.size() - 1; j >= 0; j--) {
            final Task task = mTasks.get(j);
            if (task.isVisibleForUser()) {
                task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
                task.addWindowsWaitingForDrawnIfResizingChanged();
            }
        }
    }

    /**
     * Resets the resizing state of all windows.
     */
    void endImeAdjustAnimation() {
        for (int j = mTasks.size() - 1; j >= 0; j--) {
            mTasks.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
        }
    }

    private boolean adjustForIME(final WindowState imeWin) {
        final int dockedSide = getDockSide();
        final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
@@ -946,7 +973,6 @@ public class TaskStack implements DimLayer.DimLayerUser,
            mTmpAdjustedBounds.set(mBounds);
            mTmpAdjustedBounds.top =
                    (int) (mAdjustImeAmount * top + (1 - mAdjustImeAmount) * mBounds.top);
            mTmpAdjustedBounds.bottom = mTmpAdjustedBounds.top + mBounds.height();
            mFullyAdjustedImeBounds.set(mBounds);
            mFullyAdjustedImeBounds.top = top;
            mFullyAdjustedImeBounds.bottom = top + mBounds.height();
@@ -1159,7 +1185,7 @@ public class TaskStack implements DimLayer.DimLayerUser,
        return mDragResizing;
    }

    private void setDragResizingLocked(boolean resizing) {
    void setDragResizingLocked(boolean resizing) {
        if (mDragResizing == resizing) {
            return;
        }
+2 −2
Original line number Diff line number Diff line
@@ -7459,14 +7459,14 @@ public class WindowManagerService extends IWindowManager.Stub
                    stack.setAdjustedForIme(imeWin);
                }
            }
            displayContent.mDividerControllerLocked.setAdjustedForIme(true, true);
            displayContent.mDividerControllerLocked.setAdjustedForIme(true, true, imeWin);
        } else {
            final ArrayList<TaskStack> stacks = displayContent.getStacks();
            for (int i = stacks.size() - 1; i >= 0; --i) {
                final TaskStack stack = stacks.get(i);
                stack.resetAdjustedForIme(!dockVisible);
            }
            displayContent.mDividerControllerLocked.setAdjustedForIme(false, dockVisible);
            displayContent.mDividerControllerLocked.setAdjustedForIme(false, dockVisible, imeWin);
        }
    }

+32 −2
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.AppWindowAnimator.sDummyAnimation;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
@@ -183,6 +183,8 @@ class WindowStateAnimator {
     * window is first added or shown, cleared when the callback has been made. */
    boolean mEnteringAnimation;

    private boolean mAnimationStartDelayed;

    boolean mKeyguardGoingAwayAnimation;
    boolean mKeyguardGoingAwayWithWallpaper;

@@ -299,7 +301,7 @@ class WindowStateAnimator {
    /** Is the window animating the DummyAnimation? */
    boolean isDummyAnimation() {
        return mAppAnimator != null
                && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
                && mAppAnimator.animation == sDummyAnimation;
    }

    /** Is this window currently set to animate or currently animating? */
@@ -323,8 +325,12 @@ class WindowStateAnimator {
        if ((mAnimation == null) || !mLocalAnimating) {
            return false;
        }
        currentTime = getAnimationFrameTime(mAnimation, currentTime);
        mTransformation.clear();
        final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
        if (mAnimationStartDelayed && mAnimationIsEntrance) {
            mTransformation.setAlpha(0f);
        }
        if (false && DEBUG_ANIM) Slog.v(TAG, "Stepped animation in " + this + ": more=" + more
                + ", xform=" + mTransformation);
        return more;
@@ -1841,6 +1847,9 @@ class WindowStateAnimator {
                    pw.print(" mDsDy="); pw.print(mDsDy);
                    pw.print(" mDtDy="); pw.println(mDtDy);
        }
        if (mAnimationStartDelayed) {
            pw.print(prefix); pw.print("mAnimationStartDelayed="); pw.print(mAnimationStartDelayed);
        }
    }

    @Override
@@ -1919,4 +1928,25 @@ class WindowStateAnimator {
                    mDeferTransactionUntilFrame);
        }
    }

    /**
     * Sometimes we need to synchronize the first frame of animation with some external event.
     * To achieve this, we prolong the start of the animation and keep producing the first frame of
     * the animation.
     */
    private long getAnimationFrameTime(Animation animation, long currentTime) {
        if (mAnimationStartDelayed) {
            animation.setStartTime(currentTime);
            return currentTime + 1;
        }
        return currentTime;
    }

    void startDelayingAnimationStart() {
        mAnimationStartDelayed = true;
    }

    void endDelayingAnimationStart() {
        mAnimationStartDelayed = false;
    }
}