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

Commit 72289146 authored by Tiger Huang's avatar Tiger Huang Committed by Android (Google) Code Review
Browse files

Merge "Enable InsetsState to store sources with discontinuous IDs"

parents d610595e 98f9d6bf
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -133,7 +133,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
        // If we had a request before to show from IME (tracked with mImeRequestedShow), reaching
        // this code here means that we now got control, so we can start the animation immediately.
        // If client window is trying to control IME and IME is already visible, it is immediate.
        if (fromIme || (mState.getSource(getId()).isVisible() && getControl() != null)) {
        if (fromIme
                || (mState.isSourceOrDefaultVisible(getId(), getType()) && getControl() != null)) {
            return ShowResult.SHOW_IMMEDIATELY;
        }

+11 −7
Original line number Diff line number Diff line
@@ -417,7 +417,7 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
                // control may be null if it got revoked.
                continue;
            }
            state.getSource(control.getId()).setVisible(shown);
            state.setSourceVisible(control.getId(), shown);
        }
        return getInsetsFromState(state, frame, typeSideMap);
    }
@@ -435,7 +435,8 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
                // control may be null if it got revoked.
                continue;
            }
            if (state == null || state.getSource(control.getId()).isVisible()) {
            if (state == null
                    || state.isSourceOrDefaultVisible(control.getId(), control.getType())) {
                insets = Insets.max(insets, control.getInsetsHint());
            }
        }
@@ -465,20 +466,23 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
        // TODO: Implement behavior when inset spans over multiple types
        for (int i = controls.size() - 1; i >= 0; i--) {
            final InsetsSourceControl control = controls.valueAt(i);
            final InsetsSource source = mInitialInsetsState.getSource(control.getId());
            final InsetsSource source = mInitialInsetsState.peekSource(control.getId());
            final SurfaceControl leash = control.getLeash();

            mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y);
            if (source != null) {
                mTmpFrame.set(source.getFrame());
            }
            addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame);

            final boolean visible = mHasZeroInsetsIme && side == ISIDE_BOTTOM
                    ? (mAnimationType == ANIMATION_TYPE_SHOW || !mFinished)
                    : inset != 0;

            if (outState != null) {
                outState.getSource(source.getId()).setVisible(visible);
                outState.getSource(source.getId()).setFrame(mTmpFrame);
            if (outState != null && source != null) {
                outState.getOrCreateSource(source.getId(), source.getType())
                        .setVisible(visible)
                        .setFrame(mTmpFrame);
            }

            // If the system is controlling the insets source, the leash can be null.
+88 −65
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.ime;

import android.animation.AnimationHandler;
@@ -44,13 +45,12 @@ import android.os.IBinder;
import android.os.Process;
import android.os.Trace;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsSourceConsumer.ShowResult;
import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
@@ -621,6 +621,79 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    private final Runnable mInvokeControllableInsetsChangedListeners =
            this::invokeControllableInsetsChangedListeners;

    private final InsetsState.OnTraverseCallbacks mRemoveGoneSources =
            new InsetsState.OnTraverseCallbacks() {

                private final IntArray mPendingRemoveIndexes = new IntArray();

                @Override
                public void onIdNotFoundInState2(int index1, InsetsSource source1) {
                    if (!CAPTION_ON_SHELL && source1.getType() == captionBar()) {
                        return;
                    }

                    // Don't change the indexes of the sources while traversing. Remove it later.
                    mPendingRemoveIndexes.add(index1);

                    // Remove the consumer as well except the IME one. IME consumer should always
                    // be there since we need to communicate with InputMethodManager no matter we
                    // have the source or not.
                    if (source1.getType() != ime()) {
                        mSourceConsumers.remove(source1.getId());
                    }
                }

                @Override
                public void onFinish(InsetsState state1, InsetsState state2) {
                    for (int i = mPendingRemoveIndexes.size() - 1; i >= 0; i--) {
                        state1.removeSourceAt(mPendingRemoveIndexes.get(i));
                    }
                    mPendingRemoveIndexes.clear();
                }
            };

    private final InsetsState.OnTraverseCallbacks mStartResizingAnimationIfNeeded =
            new InsetsState.OnTraverseCallbacks() {

                private @InsetsType int mTypes;
                private InsetsState mToState;

                @Override
                public void onStart(InsetsState state1, InsetsState state2) {
                    mTypes = 0;
                    mToState = null;
                }

                @Override
                public void onIdMatch(InsetsSource source1, InsetsSource source2) {
                    final @InsetsType int type = source1.getType();
                    if ((type & Type.systemBars()) == 0
                            || !source1.isVisible() || !source2.isVisible()
                            || source1.getFrame().equals(source2.getFrame())
                            || !(Rect.intersects(mFrame, source1.getFrame())
                                    || Rect.intersects(mFrame, source2.getFrame()))) {
                        return;
                    }
                    mTypes |= type;
                    if (mToState == null) {
                        mToState = new InsetsState();
                    }
                    mToState.addSource(new InsetsSource(source2));
                }

                @Override
                public void onFinish(InsetsState state1, InsetsState state2) {
                    if (mTypes == 0) {
                        return;
                    }
                    cancelExistingControllers(mTypes);
                    final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner(
                            mFrame, state1, mToState, RESIZE_INTERPOLATOR,
                            ANIMATION_DURATION_RESIZE, mTypes, InsetsController.this);
                    mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType()));
                }
            };

    public InsetsController(Host host) {
        this(host, (controller, source) -> {
            if (source.getType() == ime()) {
@@ -739,29 +812,21 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                true /* excludeInvisibleIme */)) {
            if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
            mHost.notifyInsetsChanged();
            startResizingAnimationIfNeeded(lastState);
            if (lastState.getDisplayFrame().equals(mState.getDisplayFrame())) {
                InsetsState.traverse(lastState, mState, mStartResizingAnimationIfNeeded);
            }
        }
        return true;
    }

    private void updateState(InsetsState newState) {
        mState.set(newState, 0 /* types */);
        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
            final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
            final InsetsSource source = newState.peekSource(consumer.getId());
            if (source == null && consumer != mImeSourceConsumer) {
                // IME source consumer should always be there since we need to communicate with
                // InputMethodManager no matter we have the source or not.
                mSourceConsumers.removeAt(i);
            }
        }
        @InsetsType int existingTypes = 0;
        @InsetsType int visibleTypes = 0;
        @InsetsType int disabledUserAnimationTypes = 0;
        @InsetsType int[] cancelledUserAnimationTypes = {0};
        for (int i = 0; i < InsetsState.SIZE; i++) {
            InsetsSource source = newState.peekSource(i);
            if (source == null) continue;
        for (int i = 0, size = newState.sourceSize(); i < size; i++) {
            final InsetsSource source = newState.sourceAt(i);
            @InsetsType int type = source.getType();
            @AnimationType int animationType = getAnimationType(type);
            if (!source.isUserControllable()) {
@@ -789,15 +854,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            }
            mVisibleTypes = visibleTypes;
        }
        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
            // Only update the server side insets here.
            if (!CAPTION_ON_SHELL && type == ITYPE_CAPTION_BAR) continue;
            InsetsSource source = mState.peekSource(type);
            if (source == null) continue;
            if (newState.peekSource(type) == null) {
                mState.removeSource(type);
            }
        }
        InsetsState.traverse(mState, newState, mRemoveGoneSources);

        updateDisabledUserAnimationTypes(disabledUserAnimationTypes);

@@ -825,52 +882,17 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        if (CAPTION_ON_SHELL) {
            return false;
        }
        if (mState.peekSource(ITYPE_CAPTION_BAR) == null
                && mCaptionInsetsHeight == 0) {
        final InsetsSource source = mState.peekSource(ITYPE_CAPTION_BAR);
        if (source == null && mCaptionInsetsHeight == 0) {
            return false;
        }
        if (mState.peekSource(ITYPE_CAPTION_BAR) != null
                && mCaptionInsetsHeight
                == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) {
        if (source != null && mCaptionInsetsHeight == source.getFrame().height()) {
            return false;
        }

        return true;
    }

    private void startResizingAnimationIfNeeded(InsetsState fromState) {
        if (!fromState.getDisplayFrame().equals(mState.getDisplayFrame())) {
            return;
        }
        @InsetsType int types = 0;
        InsetsState toState = null;
        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(Type.systemBars());
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
            final @InternalInsetsType int type = internalTypes.valueAt(i);
            final InsetsSource fromSource = fromState.peekSource(type);
            final InsetsSource toSource = mState.peekSource(type);
            if (fromSource != null && toSource != null
                    && fromSource.isVisible() && toSource.isVisible()
                    && !fromSource.getFrame().equals(toSource.getFrame())
                    && (Rect.intersects(mFrame, fromSource.getFrame())
                            || Rect.intersects(mFrame, toSource.getFrame()))) {
                types |= toSource.getType();
                if (toState == null) {
                    toState = new InsetsState();
                }
                toState.addSource(new InsetsSource(toSource));
            }
        }
        if (types == 0) {
            return;
        }
        cancelExistingControllers(types);
        final InsetsAnimationControlRunner runner = new InsetsResizeAnimationRunner(
                mFrame, fromState, toState, RESIZE_INTERPOLATOR, ANIMATION_DURATION_RESIZE, types,
                this);
        mRunningAnimations.add(new RunningAnimation(runner, runner.getAnimationType()));
    }

    /**
     * @see InsetsState#calculateInsets(Rect, InsetsState, boolean, boolean, int, int, int, int,
     *      int, SparseIntArray)
@@ -1217,7 +1239,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                ImeTracker.get().onFailed(statsToken,
                        ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION);

                if (fromIme && !mState.getSource(mImeSourceConsumer.getId()).isVisible()) {
                if (fromIme
                        && !mState.isSourceOrDefaultVisible(mImeSourceConsumer.getId(), ime())) {
                    // We've requested IMM to show IME, but the IME is not controllable. We need to
                    // cancel the request.
                    setRequestedVisibleTypes(0 /* visibleTypes */, ime());
@@ -1757,8 +1780,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        if (mCaptionInsetsHeight != height) {
            mCaptionInsetsHeight = height;
            if (mCaptionInsetsHeight != 0) {
                mState.getSource(ITYPE_CAPTION_BAR).setFrame(mFrame.left, mFrame.top,
                        mFrame.right, mFrame.top + mCaptionInsetsHeight);
                mState.getOrCreateSource(ITYPE_CAPTION_BAR, captionBar()).setFrame(
                        mFrame.left, mFrame.top, mFrame.right, mFrame.top + mCaptionInsetsHeight);
            } else {
                mState.removeSource(ITYPE_CAPTION_BAR);
            }
+16 −18
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.animation.Interpolator;
@@ -142,12 +141,9 @@ public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner
            return false;
        }
        final float fraction = mAnimation.getInterpolatedFraction();
        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
            final InsetsSource fromSource = mFromState.peekSource(type);
            final InsetsSource toSource = mToState.peekSource(type);
            if (fromSource == null || toSource == null) {
                continue;
            }
        InsetsState.traverse(mFromState, mToState, new InsetsState.OnTraverseCallbacks() {
            @Override
            public void onIdMatch(InsetsSource fromSource, InsetsSource toSource) {
                final Rect fromFrame = fromSource.getFrame();
                final Rect toFrame = toSource.getFrame();
                final Rect frame = new Rect(
@@ -155,11 +151,13 @@ public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner
                        (int) (fromFrame.top + fraction * (toFrame.top - fromFrame.top)),
                        (int) (fromFrame.right + fraction * (toFrame.right - fromFrame.right)),
                        (int) (fromFrame.bottom + fraction * (toFrame.bottom - fromFrame.bottom)));
            final InsetsSource source = new InsetsSource(type, fromSource.getType());
                final InsetsSource source =
                        new InsetsSource(fromSource.getId(), fromSource.getType());
                source.setFrame(frame);
                source.setVisible(toSource.isVisible());
                outState.addSource(source);
            }
        });
        if (mFinished) {
            mController.notifyFinished(this, true /* shown */);
        }
+10 −5
Original line number Diff line number Diff line
@@ -83,20 +83,24 @@ public class InsetsSource implements Parcelable {
        mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
    }

    public void setFrame(int left, int top, int right, int bottom) {
    public InsetsSource setFrame(int left, int top, int right, int bottom) {
        mFrame.set(left, top, right, bottom);
        return this;
    }

    public void setFrame(Rect frame) {
    public InsetsSource setFrame(Rect frame) {
        mFrame.set(frame);
        return this;
    }

    public void setVisibleFrame(@Nullable Rect visibleFrame) {
    public InsetsSource setVisibleFrame(@Nullable Rect visibleFrame) {
        mVisibleFrame = visibleFrame != null ? new Rect(visibleFrame) : null;
        return this;
    }

    public void setVisible(boolean visible) {
    public InsetsSource setVisible(boolean visible) {
        mVisible = visible;
        return this;
    }

    public int getId() {
@@ -128,8 +132,9 @@ public class InsetsSource implements Parcelable {
        return mInsetsRoundedCornerFrame;
    }

    public void setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
    public InsetsSource setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
        mInsetsRoundedCornerFrame = insetsRoundedCornerFrame;
        return this;
    }

    /**
Loading