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

Commit afc185e9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement Transient Insets Animation"

parents dc526073 b5d2db77
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.view;

import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsState.ISIDE_BOTTOM;
import static android.view.InsetsState.ISIDE_FLOATING;
import static android.view.InsetsState.ISIDE_LEFT;
@@ -188,7 +186,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll

    @Override
    public void finish(boolean shown) {
        if (mCancelled) {
        if (mCancelled || mFinished) {
            return;
        }
        setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */);
+9 −6
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    private static final int ANIMATION_DURATION_HIDE_MS = 340;
    private static final int PENDING_CONTROL_TIMEOUT_MS = 2000;

    static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
    public static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);

    /**
     * Layout mode during insets animation: The views should be laid out as if the changing inset
@@ -78,7 +78,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
     * be called as if the changing insets types are shown, which will result in the views being
     * laid out as if the insets are fully shown.
     */
    static final int LAYOUT_INSETS_DURING_ANIMATION_SHOWN = 0;
    public static final int LAYOUT_INSETS_DURING_ANIMATION_SHOWN = 0;

    /**
     * Layout mode during insets animation: The views should be laid out as if the changing inset
@@ -86,7 +86,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
     * be called as if the changing insets types are hidden, which will result in the views being
     * laid out as if the insets are fully hidden.
     */
    static final int LAYOUT_INSETS_DURING_ANIMATION_HIDDEN = 1;
    public static final int LAYOUT_INSETS_DURING_ANIMATION_HIDDEN = 1;

    /**
     * Determines the behavior of how the views should be laid out during an insets animation that
@@ -149,7 +149,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        @Override
        public void set(WindowInsetsAnimationController controller, Insets value) {
            controller.setInsetsAndAlpha(
                    value, 1f /* alpha */, (((DefaultAnimationControlListener)
                    value, 1f /* alpha */, (((InternalAnimationControlListener)
                            ((InsetsAnimationControlImpl) controller).getListener())
                                    .getRawFraction()));
        }
@@ -166,7 +166,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        private ObjectAnimator mAnimator;
        protected boolean mShow;

        InternalAnimationControlListener(boolean show) {
        public InternalAnimationControlListener(boolean show) {
            mShow = show;
        }

@@ -214,7 +214,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            return (float) mAnimator.getCurrentPlayTime() / mAnimator.getDuration();
        }

        protected long getDurationMs() {
        /**
         * To get the animation duration in MS.
         */
        public long getDurationMs() {
            if (mAnimator != null) {
                return mAnimator.getDuration();
            }
+9 −0
Original line number Diff line number Diff line
@@ -193,6 +193,15 @@ public class InsetsSource implements Parcelable {
        dest.writeBoolean(mVisible);
    }

    @Override
    public String toString() {
        return "InsetsSource: {"
                + "mType=" + InsetsState.typeToString(mType)
                + ", mFrame=" + mFrame.toShortString()
                + ", mVisible" + mVisible
                + "}";
    }

    public static final @android.annotation.NonNull Creator<InsetsSource> CREATOR = new Creator<InsetsSource>() {

        public InsetsSource createFromParcel(Parcel in) {
+14 −3
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.IME;
import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.SIZE;
import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
@@ -43,7 +42,6 @@ import android.util.ArraySet;
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;

import java.io.PrintWriter;
@@ -366,7 +364,12 @@ public class InsetsState implements Parcelable {
        return result;
    }

    static @Type.InsetsType int toPublicType(@InternalInsetsType int type) {
    /**
     * Converting a internal type to the public type.
     * @param type internal insets type, {@code InternalInsetsType}.
     * @return public insets type, {@code Type.InsetsType}.
     */
    public static @Type.InsetsType int toPublicType(@InternalInsetsType int type) {
        switch (type) {
            case ITYPE_STATUS_BAR:
                return Type.STATUS_BARS;
@@ -510,5 +513,13 @@ public class InsetsState implements Parcelable {
            mSources.put(source.getType(), source);
        }
    }

    @Override
    public String toString() {
        return "InsetsState: {"
                + "mDisplayFrame=" + mDisplayFrame
                + ", mSources=" + mSources
                + "}";
    }
}
+151 −11
Original line number Diff line number Diff line
@@ -20,17 +20,31 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;

import android.annotation.Nullable;
import android.app.StatusBarManager;
import android.util.IntArray;
import android.util.SparseArray;
import android.view.InsetsAnimationControlCallbacks;
import android.view.InsetsAnimationControlImpl;
import android.view.InsetsController;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl;
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.ViewRootImpl;
import android.view.WindowInsetsAnimationCallback;
import android.view.WindowInsetsAnimationControlListener;

import com.android.server.DisplayThread;

/**
 * Policy that implements who gets control over the windows generating insets.
@@ -46,6 +60,8 @@ class InsetsPolicy {
    private WindowState mFocusedWin;
    private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
    private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
    private boolean mAnimatingShown;
    private final float[] mTmpFloat9 = new float[9];

    InsetsPolicy(InsetsStateController stateController, DisplayContent displayContent) {
        mStateController = stateController;
@@ -91,11 +107,14 @@ class InsetsPolicy {
            changed = true;
        }
        if (changed) {
            updateBarControlTarget(mFocusedWin);
            mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(),
            startAnimation(mShowingTransientTypes, true, () -> {
                synchronized (mDisplayContent.mWmService.mGlobalLock) {
                    mPolicy.getStatusBarManagerInternal().showTransient(
                            mDisplayContent.getDisplayId(),
                            mShowingTransientTypes.toArray());
                    mStateController.notifyInsetsChanged();
            // TODO(b/118118435): Animation
                }
            });
        }
    }

@@ -103,11 +122,13 @@ class InsetsPolicy {
        if (mShowingTransientTypes.size() == 0) {
            return;
        }

        // TODO(b/118118435): Animation
        startAnimation(mShowingTransientTypes, false, () -> {
            synchronized (mDisplayContent.mWmService.mGlobalLock) {
                mShowingTransientTypes.clear();
        updateBarControlTarget(mFocusedWin);
                mStateController.notifyInsetsChanged();
                updateBarControlTarget(mFocusedWin);
            }
        });
    }

    boolean isTransient(@InternalInsetsType int type) {
@@ -247,6 +268,29 @@ class InsetsPolicy {
        return isDockedStackVisible || isFreeformStackVisible || isResizing;
    }

    private void startAnimation(IntArray internalTypes, boolean show, Runnable callback) {
        int typesReady = 0;
        final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
        updateBarControlTarget(mFocusedWin);
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
            InsetsSourceProvider provider =
                    mStateController.getSourceProvider(internalTypes.get(i));
            if (provider == null) continue;
            InsetsSourceControl control = provider.getControl(provider.getControlTarget());
            if (control == null || control.getLeash() == null) continue;
            typesReady |= InsetsState.toPublicType(internalTypes.get(i));
            controls.put(control.getType(), control);
        }
        controlAnimationUnchecked(typesReady, controls, show, callback);
    }

    private void controlAnimationUnchecked(int typesReady,
            SparseArray<InsetsSourceControl> controls, boolean show, Runnable callback) {
        InsetsPolicyAnimationControlListener listener =
                new InsetsPolicyAnimationControlListener(show, callback);
        listener.mControlCallbacks.controlAnimationUnchecked(typesReady, controls, show);
    }

    private class BarWindow {

        private final int mId;
@@ -267,7 +311,103 @@ class InsetsPolicy {
        }
    }

    // TODO(b/118118435): Implement animations for it (with SurfaceAnimator)
    private class InsetsPolicyAnimationControlListener extends
            InsetsController.InternalAnimationControlListener {
        Runnable mFinishCallback;
        InsetsPolicyAnimationControlCallbacks mControlCallbacks;

        InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback) {
            super(show);
            mFinishCallback = finishCallback;
            mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
        }

        @Override
        protected void onAnimationFinish() {
            super.onAnimationFinish();
            mControlCallbacks.mAnimationControl.finish(mAnimatingShown);
            DisplayThread.getHandler().post(mFinishCallback);
        }

        private class InsetsPolicyAnimationControlCallbacks implements
                InsetsAnimationControlCallbacks {
            private InsetsAnimationControlImpl mAnimationControl = null;
            private InsetsPolicyAnimationControlListener mListener;

            InsetsPolicyAnimationControlCallbacks(InsetsPolicyAnimationControlListener listener) {
                super();
                mListener = listener;
            }

            private void controlAnimationUnchecked(int typesReady,
                    SparseArray<InsetsSourceControl> controls, boolean show) {
                if (typesReady == 0) {
                    // nothing to animate.
                    return;
                }
                mAnimatingShown = show;

                mAnimationControl = new InsetsAnimationControlImpl(controls,
                        mFocusedWin.getDisplayContent().getBounds(), getState(),
                        mListener, typesReady, this, mListener.getDurationMs(),
                        InsetsController.INTERPOLATOR, true,
                        show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
                                : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
            }

            /** Called on SurfaceAnimationThread lock without global WM lock held. */
            @Override
            public void scheduleApplyChangeInsets() {
                InsetsState state = getState();
                if (mAnimationControl.applyChangeInsets(state)) {
                    mAnimationControl.finish(mAnimatingShown);
                }
            }

            @Override
            public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
                // Nothing's needed here. Finish steps is handled in the listener
                // onAnimationFinished callback.
            }

            /**
             * This method will return a state with fullscreen frame override. No need to make copy
             * after getting state from this method.
             * @return The client insets state with full display frame override.
             */
            private InsetsState getState() {
                // To animate the transient animation correctly, we need to let the state hold
                // the full display frame.
                InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(),
                        true);
                overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds());
                return overrideState;
            }

            /** Called on SurfaceAnimationThread lock without global WM lock held. */
            @Override
            public void applySurfaceParams(
                    final SyncRtSurfaceTransactionApplier.SurfaceParams... params) {
                SurfaceControl.Transaction t = new SurfaceControl.Transaction();
                for (int i = params.length - 1; i >= 0; i--) {
                    SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i];
                    applyParams(t, surfaceParams, mTmpFloat9);
                }
                t.apply();
            }

            /** Called on SurfaceAnimationThread lock without global WM lock held. */
            @Override
            public void startAnimation(InsetsAnimationControlImpl controller,
                    WindowInsetsAnimationControlListener listener, int types,
                    WindowInsetsAnimationCallback.InsetsAnimation animation,
                    WindowInsetsAnimationCallback.AnimationBounds bounds,
                    int layoutDuringAnimation) {
                SurfaceAnimationThread.getHandler().post(() -> listener.onReady(controller, types));
            }
        }
    }

    private class TransientControlTarget implements InsetsControlTarget {

        @Override