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

Commit 80b277ea authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Move DividerImeController into its own top-level class" into rvc-dev am: b82aaa58

Change-Id: I9569b98efc4b39cf4573c1278d87df1cff78f5c8
parents 83e70ab5 b82aaa58
Loading
Loading
Loading
Loading
+6 −307
Original line number Original line Diff line number Diff line
@@ -18,15 +18,10 @@ package com.android.systemui.stackdivider;


import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;


import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;


import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.Context;
@@ -36,15 +31,11 @@ import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings;
import android.util.Slog;
import android.util.Slog;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.View;
import android.view.View;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
import android.window.WindowOrganizer;


import androidx.annotation.Nullable;

import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUI;
@@ -81,7 +72,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
    static final boolean DEBUG = false;
    static final boolean DEBUG = false;


    static final int DEFAULT_APP_TRANSITION_DURATION = 336;
    static final int DEFAULT_APP_TRANSITION_DURATION = 336;
    static final float ADJUSTED_NONFOCUS_DIM = 0.3f;


    private final Optional<Lazy<Recents>> mRecentsOptionalLazy;
    private final Optional<Lazy<Recents>> mRecentsOptionalLazy;


@@ -139,303 +129,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
                }
                }
            };
            };


    private class DividerImeController implements DisplayImeController.ImePositionProcessor {
    private final DividerImeController mImePositionProcessor;
        /**
         * These are the y positions of the top of the IME surface when it is hidden and when it is
         * shown respectively. These are NOT necessarily the top of the visible IME itself.
         */
        private int mHiddenTop = 0;
        private int mShownTop = 0;

        // The following are target states (what we are curretly animating towards).
        /**
         * {@code true} if, at the end of the animation, the split task positions should be
         * adjusted by height of the IME. This happens when the secondary split is the IME target.
         */
        private boolean mTargetAdjusted = false;
        /**
         * {@code true} if, at the end of the animation, the IME should be shown/visible
         * regardless of what has focus.
         */
        private boolean mTargetShown = false;
        private float mTargetPrimaryDim = 0.f;
        private float mTargetSecondaryDim = 0.f;

        // The following are the current (most recent) states set during animation
        /** {@code true} if the secondary split has IME focus. */
        private boolean mSecondaryHasFocus = false;
        /** The dimming currently applied to the primary/secondary splits. */
        private float mLastPrimaryDim = 0.f;
        private float mLastSecondaryDim = 0.f;
        /** The most recent y position of the top of the IME surface */
        private int mLastAdjustTop = -1;

        // The following are states reached last time an animation fully completed.
        /** {@code true} if the IME was shown/visible by the last-completed animation. */
        private boolean mImeWasShown = false;
        /** {@code true} if the split positions were adjusted by the last-completed animation. */
        private boolean mAdjusted = false;

        /**
         * When some aspect of split-screen needs to animate independent from the IME,
         * this will be non-null and control split animation.
         */
        @Nullable
        private ValueAnimator mAnimation = null;

        private boolean mPaused = true;
        private boolean mPausedTargetAdjusted = false;

        private boolean getSecondaryHasFocus(int displayId) {
            WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId);
            return imeSplit != null
                    && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
        }

        private void updateDimTargets() {
            final boolean splitIsVisible = !mView.isHidden();
            mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
                    ? ADJUSTED_NONFOCUS_DIM : 0.f;
            mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
                    ? ADJUSTED_NONFOCUS_DIM : 0.f;
        }

        @Override
        public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
                boolean imeShouldShow, SurfaceControl.Transaction t) {
            if (!isDividerVisible()) {
                return;
            }
            final boolean splitIsVisible = !mView.isHidden();
            mSecondaryHasFocus = getSecondaryHasFocus(displayId);
            final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
                    && !mSplitLayout.mDisplayLayout.isLandscape();
            mHiddenTop = hiddenTop;
            mShownTop = shownTop;
            mTargetShown = imeShouldShow;
            if (mLastAdjustTop < 0) {
                mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
            } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
                if (mTargetAdjusted != targetAdjusted && targetAdjusted == mAdjusted) {
                    // Check for an "interruption" of an existing animation. In this case, we
                    // need to fake-flip the last-known state direction so that the animation
                    // completes in the other direction.
                    mAdjusted = mTargetAdjusted;
                } else if (targetAdjusted && mTargetAdjusted && mAdjusted) {
                    // Already fully adjusted for IME, but IME height has changed; so, force-start
                    // an async animation to the new IME height.
                    mAdjusted = false;
                }
            }
            if (mPaused) {
                mPausedTargetAdjusted = targetAdjusted;
                if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
                return;
            }
            mTargetAdjusted = targetAdjusted;
            updateDimTargets();
            if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + "  " + dumpState());
            if (mAnimation != null || (mImeWasShown && imeShouldShow
                    && mTargetAdjusted != mAdjusted)) {
                // We need to animate adjustment independently of the IME position, so
                // start our own animation to drive adjustment. This happens when a
                // different split's editor has gained focus while the IME is still visible.
                startAsyncAnimation();
            }
            if (splitIsVisible) {
                // If split is hidden, we don't want to trigger any relayouts that would cause the
                // divider to show again.
                updateImeAdjustState();
            }
        }

        private void updateImeAdjustState() {
            // Reposition the server's secondary split position so that it evaluates
            // insets properly.
            WindowContainerTransaction wct = new WindowContainerTransaction();
            if (mTargetAdjusted) {
                mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
                wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary);
                // "Freeze" the configuration size so that the app doesn't get a config
                // or relaunch. This is required because normally nav-bar contributes
                // to configuration bounds (via nondecorframe).
                Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
                        .windowConfiguration.getAppBounds());
                adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top
                        - mSplitLayout.mSecondary.top);
                wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
                wct.setScreenSizeDp(mSplits.mSecondary.token,
                        mSplits.mSecondary.configuration.screenWidthDp,
                        mSplits.mSecondary.configuration.screenHeightDp);

                wct.setBounds(mSplits.mPrimary.token, mSplitLayout.mAdjustedPrimary);
                adjustAppBounds = new Rect(mSplits.mPrimary.configuration
                        .windowConfiguration.getAppBounds());
                adjustAppBounds.offset(0, mSplitLayout.mAdjustedPrimary.top
                        - mSplitLayout.mPrimary.top);
                wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
                wct.setScreenSizeDp(mSplits.mPrimary.token,
                        mSplits.mPrimary.configuration.screenWidthDp,
                        mSplits.mPrimary.configuration.screenHeightDp);
            } else {
                wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary);
                wct.setAppBounds(mSplits.mSecondary.token, null);
                wct.setScreenSizeDp(mSplits.mSecondary.token,
                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
                wct.setBounds(mSplits.mPrimary.token, mSplitLayout.mPrimary);
                wct.setAppBounds(mSplits.mPrimary.token, null);
                wct.setScreenSizeDp(mSplits.mPrimary.token,
                        SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
            }

            WindowOrganizer.applyTransaction(wct);

            // Update all the adjusted-for-ime states
            if (!mPaused) {
                mView.setAdjustedForIme(mTargetShown, mTargetShown
                        ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
                        : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
            }
            setAdjustedForIme(mTargetShown && !mPaused);
        }

        @Override
        public void onImePositionChanged(int displayId, int imeTop,
                SurfaceControl.Transaction t) {
            if (mAnimation != null || !isDividerVisible() || mPaused) {
                // Not synchronized with IME anymore, so return.
                return;
            }
            final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop);
            final float progress = mTargetShown ? fraction : 1.f - fraction;
            onProgress(progress, t);
        }

        @Override
        public void onImeEndPositioning(int displayId, boolean cancelled,
                SurfaceControl.Transaction t) {
            if (mAnimation != null || !isDividerVisible() || mPaused) {
                // Not synchronized with IME anymore, so return.
                return;
            }
            onEnd(cancelled, t);
        }

        private void onProgress(float progress, SurfaceControl.Transaction t) {
            if (mTargetAdjusted != mAdjusted && !mPaused) {
                final float fraction = mTargetAdjusted ? progress : 1.f - progress;
                mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
                mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
                mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary,
                        mSplitLayout.mAdjustedSecondary);
            }
            final float invProg = 1.f - progress;
            mView.setResizeDimLayer(t, true /* primary */,
                    mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
            mView.setResizeDimLayer(t, false /* primary */,
                    mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
        }

        private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
            if (!cancelled) {
                onProgress(1.f, t);
                mAdjusted = mTargetAdjusted;
                mImeWasShown = mTargetShown;
                mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
                mLastPrimaryDim = mTargetPrimaryDim;
                mLastSecondaryDim = mTargetSecondaryDim;
            }
        }

        private void startAsyncAnimation() {
            if (mAnimation != null) {
                mAnimation.cancel();
            }
            mAnimation = ValueAnimator.ofFloat(0.f, 1.f);
            mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS);
            if (mTargetAdjusted != mAdjusted) {
                final float fraction =
                        ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop);
                final float progress = mTargetAdjusted ? fraction : 1.f - fraction;
                mAnimation.setCurrentFraction(progress);
            }

            mAnimation.addUpdateListener(animation -> {
                SurfaceControl.Transaction t = mTransactionPool.acquire();
                float value = (float) animation.getAnimatedValue();
                onProgress(value, t);
                t.apply();
                mTransactionPool.release(t);
            });
            mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
            mAnimation.addListener(new AnimatorListenerAdapter() {
                private boolean mCancel = false;
                @Override
                public void onAnimationCancel(Animator animation) {
                    mCancel = true;
                }
                @Override
                public void onAnimationEnd(Animator animation) {
                    SurfaceControl.Transaction t = mTransactionPool.acquire();
                    onEnd(mCancel, t);
                    t.apply();
                    mTransactionPool.release(t);
                    mAnimation = null;
                }
            });
            mAnimation.start();
        }

        private String dumpState() {
            return "top:" + mHiddenTop + "->" + mShownTop
                    + " adj:" + mAdjusted + "->" + mTargetAdjusted + "(" + mLastAdjustTop + ")"
                    + " shw:" + mImeWasShown + "->" + mTargetShown
                    + " dims:" + mLastPrimaryDim + "," + mLastSecondaryDim
                    + "->" + mTargetPrimaryDim + "," + mTargetSecondaryDim
                    + " shf:" + mSecondaryHasFocus + " desync:" + (mAnimation != null)
                    + " paus:" + mPaused + "[" + mPausedTargetAdjusted + "]";
        }

        /** Completely aborts/resets adjustment state */
        public void pause(int displayId) {
            if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
            mHandler.post(() -> {
                if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
                if (mPaused) {
                    return;
                }
                mPaused = true;
                mPausedTargetAdjusted = mTargetAdjusted;
                mTargetAdjusted = false;
                mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
                updateImeAdjustState();
                startAsyncAnimation();
                if (mAnimation != null) {
                    mAnimation.end();
                }
            });
        }

        public void resume(int displayId) {
            if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
            mHandler.post(() -> {
                if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
                if (!mPaused) {
                    return;
                }
                mPaused = false;
                mTargetAdjusted = mPausedTargetAdjusted;
                updateDimTargets();
                if ((mTargetAdjusted != mAdjusted) && !mMinimized && mView != null) {
                    // End unminimize animations since they conflict with adjustment animations.
                    mView.finishAnimations();
                }
                updateImeAdjustState();
                startAsyncAnimation();
            });
        }
    }
    private final DividerImeController mImePositionProcessor = new DividerImeController();


    private TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
    private TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
        @Override
        @Override
@@ -465,6 +159,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
        mRecentsOptionalLazy = recentsOptionalLazy;
        mRecentsOptionalLazy = recentsOptionalLazy;
        mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
        mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
        mTransactionPool = transactionPool;
        mTransactionPool = transactionPool;
        mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler);
    }
    }


    @Override
    @Override
@@ -830,6 +525,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
        }
        }
    }
    }


    SplitDisplayLayout getSplitLayout() {
        return mSplitLayout;
    }

    /** @return the container token for the secondary split root task. */
    /** @return the container token for the secondary split root task. */
    public WindowContainerToken getSecondaryRoot() {
    public WindowContainerToken getSecondaryRoot() {
        if (mSplits == null || mSplits.mSecondary == null) {
        if (mSplits == null || mSplits.mSecondary == null) {
+368 −0

File added.

Preview size limit exceeded, changes collapsed.