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

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

Merge "Let insets can still be controlled if its window bounds is moved" into sc-dev

parents b3705153 7faf533f
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
@@ -28,6 +29,7 @@ import android.os.Build.VERSION_CODES;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayMetrics;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.WindowManager;
@@ -423,12 +425,37 @@ public class CompatibilityInfo implements Parcelable {
        }

        /**
         * Translate an InsetsState in screen coordinates into the app window's coordinates.
         * Translate an {@link InsetsState} in screen coordinates into the app window's coordinates.
         */
        public void translateInsetsStateInScreenToAppWindow(InsetsState state) {
            state.scale(applicationInvertedScale);
        }

        /**
         * Translate {@link InsetsSourceControl}s in screen coordinates into the app window's
         * coordinates.
         */
        public void translateSourceControlsInScreenToAppWindow(InsetsSourceControl[] controls) {
            if (controls == null) {
                return;
            }
            final float scale = applicationInvertedScale;
            if (scale == 1f) {
                return;
            }
            for (InsetsSourceControl control : controls) {
                if (control == null) {
                    continue;
                }
                final Insets hint = control.getInsetsHint();
                control.setInsetsHint(
                        (int) (scale * hint.left),
                        (int) (scale * hint.top),
                        (int) (scale * hint.right),
                        (int) (scale * hint.bottom));
            }
        }

        /**
         * Translate a Point in screen coordinates into the app window's coordinates.
         */
+92 −44
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsController.AnimationType;
import static android.view.InsetsController.DEBUG;
import static android.view.InsetsState.ISIDE_BOTTOM;
import static android.view.InsetsState.ISIDE_FLOATING;
import static android.view.InsetsState.ISIDE_LEFT;
import static android.view.InsetsState.ISIDE_RIGHT;
import static android.view.InsetsState.ISIDE_TOP;
@@ -74,8 +75,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll

    private final WindowInsetsAnimationControlListener mListener;
    private final SparseArray<InsetsSourceControl> mControls;
    private final SparseIntArray mTypeSideMap = new SparseIntArray();
    private final SparseSetArray<InsetsSourceControl> mSideSourceMap = new SparseSetArray<>();
    private final SparseSetArray<InsetsSourceControl> mSideControlsMap = new SparseSetArray<>();

    /** @see WindowInsetsAnimationController#getHiddenStateInsets */
    private final Insets mHiddenInsets;
@@ -104,8 +104,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
    private Boolean mPerceptible;

    @VisibleForTesting
    public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame,
            InsetsState state, WindowInsetsAnimationControlListener listener,
    public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls,
            @Nullable Rect frame, InsetsState state, WindowInsetsAnimationControlListener listener,
            @InsetsType int types,
            InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
            @AnimationType int animationType, CompatibilityInfo.Translator translator) {
@@ -114,19 +114,30 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
        mTypes = types;
        mController = controller;
        mInitialInsetsState = new InsetsState(state, true /* copySources */);
        if (frame != null) {
            final SparseIntArray typeSideMap = new SparseIntArray();
            mCurrentInsets = getInsetsFromState(mInitialInsetsState, frame, null /* typeSideMap */);
        mPendingInsets = mCurrentInsets;
            mHiddenInsets = calculateInsets(mInitialInsetsState, frame, controls, false /* shown */,
                    null /* typeSideMap */);
            mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */,
                mTypeSideMap);
                    typeSideMap);
            mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsInternalType(ITYPE_IME);
            if (mHasZeroInsetsIme) {
                // IME has shownInsets of ZERO, and can't map to a side by default.
                // Map zero insets IME to bottom, making it a special case of bottom insets.
            mTypeSideMap.put(ITYPE_IME, ISIDE_BOTTOM);
                typeSideMap.put(ITYPE_IME, ISIDE_BOTTOM);
            }
            buildSideControlsMap(typeSideMap, mSideControlsMap, controls);
        } else {
            // Passing a null frame indicates the caller wants to play the insets animation anyway,
            // no matter the source provides insets to the frame or not.
            mCurrentInsets = calculateInsets(mInitialInsetsState, controls, true /* shown */);
            mHiddenInsets = calculateInsets(null, controls, false /* shown */);
            mShownInsets = calculateInsets(null, controls, true /* shown */);
            mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsInternalType(ITYPE_IME);
            buildSideControlsMap(mSideControlsMap, controls);
        }
        buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls);
        mPendingInsets = mCurrentInsets;

        mAnimation = new WindowInsetsAnimation(mTypes, interpolator,
                durationMs);
@@ -312,32 +323,52 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
        proto.end(token);
    }

    WindowInsetsAnimationControlListener getListener() {
        return mListener;
    }

    SparseArray<InsetsSourceControl> getControls() {
        return mControls;
    }

    private Insets getInsetsFromState(InsetsState state, Rect frame,
            @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
        return state.calculateInsets(frame, null /* ignoringVisibilityState */,
                false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
                LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
                0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
                WINDOWING_MODE_UNDEFINED, typeSideMap).getInsets(mTypes);
    }

    /** Computes the insets relative to the given frame. */
    private Insets calculateInsets(InsetsState state, Rect frame,
            SparseArray<InsetsSourceControl> controls, boolean shown,
            @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
        for (int i = controls.size() - 1; i >= 0; i--) {
            final InsetsSourceControl control  = controls.valueAt(i);
            if (control == null) {
                // control may be null if it got revoked.
            if (controls.valueAt(i) == null) continue;
            state.getSource(controls.valueAt(i).getType()).setVisible(shown);
                continue;
            }
            state.getSource(control.getType()).setVisible(shown);
        }
        return getInsetsFromState(state, frame, typeSideMap);
    }

    private Insets getInsetsFromState(InsetsState state, Rect frame,
            @Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
        return state.calculateInsets(frame, null /* ignoringVisibilityState */,
                false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
                LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/,
                0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, TYPE_APPLICATION,
                WINDOWING_MODE_UNDEFINED, typeSideMap).getInsets(mTypes);
    /** Computes the insets from the insets hints of controls. */
    private Insets calculateInsets(InsetsState state, SparseArray<InsetsSourceControl> controls,
            boolean shownOrCurrent) {
        Insets insets = Insets.NONE;
        if (!shownOrCurrent) {
            return insets;
        }
        for (int i = controls.size() - 1; i >= 0; i--) {
            final InsetsSourceControl control  = controls.valueAt(i);
            if (control == null) {
                // control may be null if it got revoked.
                continue;
            }
            if (state == null || state.getSource(control.getType()).isVisible()) {
                insets = Insets.max(insets, control.getInsetsHint());
            }
        }
        return insets;
    }

    private Insets sanitize(Insets insets) {
@@ -356,13 +387,13 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll

    private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset,
            ArrayList<SurfaceParams> surfaceParams, @Nullable InsetsState outState, float alpha) {
        ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side);
        if (items == null) {
        final ArraySet<InsetsSourceControl> controls = mSideControlsMap.get(side);
        if (controls == null) {
            return;
        }
        // TODO: Implement behavior when inset spans over multiple types
        for (int i = items.size() - 1; i >= 0; i--) {
            final InsetsSourceControl control = items.valueAt(i);
        for (int i = controls.size() - 1; i >= 0; i--) {
            final InsetsSourceControl control = controls.valueAt(i);
            final InsetsSource source = mInitialInsetsState.getSource(control.getType());
            final SurfaceControl leash = control.getLeash();

@@ -371,7 +402,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
            addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame);

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

            if (outState != null) {
@@ -391,32 +422,32 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
        }
    }

    private void addTranslationToMatrix(@InternalInsetsSide int side, int inset, Matrix m,
    private void addTranslationToMatrix(@InternalInsetsSide int side, int offset, Matrix m,
            Rect frame) {
        final float surfaceOffset = mTranslator != null
                ? mTranslator.translateLengthInAppWindowToScreen(inset) : inset;
                ? mTranslator.translateLengthInAppWindowToScreen(offset) : offset;
        switch (side) {
            case ISIDE_LEFT:
                m.postTranslate(-surfaceOffset, 0);
                frame.offset(-inset, 0);
                frame.offset(-offset, 0);
                break;
            case ISIDE_TOP:
                m.postTranslate(0, -surfaceOffset);
                frame.offset(0, -inset);
                frame.offset(0, -offset);
                break;
            case ISIDE_RIGHT:
                m.postTranslate(surfaceOffset, 0);
                frame.offset(inset, 0);
                frame.offset(offset, 0);
                break;
            case ISIDE_BOTTOM:
                m.postTranslate(0, surfaceOffset);
                frame.offset(0, inset);
                frame.offset(0, offset);
                break;
        }
    }

    private static void buildTypeSourcesMap(SparseIntArray typeSideMap,
            SparseSetArray<InsetsSourceControl> sideSourcesMap,
    private static void buildSideControlsMap(SparseIntArray typeSideMap,
            SparseSetArray<InsetsSourceControl> sideControlsMap,
            SparseArray<InsetsSourceControl> controls) {
        for (int i = typeSideMap.size() - 1; i >= 0; i--) {
            final int type = typeSideMap.keyAt(i);
@@ -427,7 +458,24 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
                // there can be some null controllers.
                continue;
            }
            sideSourcesMap.add(side, control);
            sideControlsMap.add(side, control);
        }
    }

    private static void buildSideControlsMap(
            SparseSetArray<InsetsSourceControl> sideControlsMap,
            SparseArray<InsetsSourceControl> controls) {
        for (int i = controls.size() - 1; i >= 0; i--) {
            final InsetsSourceControl control  = controls.valueAt(i);
            if (control == null) {
                // control may be null if it got revoked.
                continue;
            }
            @InternalInsetsSide int side = InsetsState.getInsetSide(control.getInsetsHint());
            if (side == ISIDE_FLOATING && control.getType() == ITYPE_IME) {
                side = ISIDE_BOTTOM;
            }
            sideControlsMap.add(side, control);
        }
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.view;
import static android.view.InsetsController.DEBUG;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;

import android.annotation.Nullable;
import android.annotation.UiThread;
import android.content.res.CompatibilityInfo;
import android.graphics.Rect;
@@ -100,8 +101,8 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
    };

    @UiThread
    public InsetsAnimationThreadControlRunner(SparseArray<InsetsSourceControl> controls, Rect frame,
            InsetsState state, WindowInsetsAnimationControlListener listener,
    public InsetsAnimationThreadControlRunner(SparseArray<InsetsSourceControl> controls,
            @Nullable Rect frame, InsetsState state, WindowInsetsAnimationControlListener listener,
            @InsetsType int types,
            InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
            @AnimationType int animationType, CompatibilityInfo.Translator translator,
+8 −5
Original line number Diff line number Diff line
@@ -837,9 +837,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            PendingControlRequest pendingRequest = mPendingImeControlRequest;
            mPendingImeControlRequest = null;
            mHandler.removeCallbacks(mPendingControlTimeout);

            // We are about to playing the default animation. Passing a null frame indicates the
            // controlled types should be animated regardless of the frame.
            controlAnimationUnchecked(
                    pendingRequest.types, pendingRequest.cancellationSignal,
                    pendingRequest.listener, mFrame,
                    pendingRequest.listener, null /* frame */,
                    true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
                    pendingRequest.animationType,
                    pendingRequest.layoutInsetsDuringAnimation,
@@ -934,7 +937,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    private void controlAnimationUnchecked(@InsetsType int types,
            @Nullable CancellationSignal cancellationSignal,
            WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme,
            WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme,
            long durationMs, Interpolator interpolator,
            @AnimationType int animationType,
            @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
@@ -1358,10 +1361,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                show, hasAnimationCallbacks, types, skipAnim || mAnimationsDisabled,
                mHost.dipToPx(InternalAnimationControlListener.FLOATING_IME_BOTTOM_INSET));

        // Show/hide animations always need to be relative to the display frame, in order that shown
        // and hidden state insets are correct.
        // We are about to playing the default animation (show/hide). Passing a null frame indicates
        // the controlled types should be animated regardless of the frame.
        controlAnimationUnchecked(
                types, null /* cancellationSignal */, listener, mState.getDisplayFrame(), fromIme,
                types, null /* cancellationSignal */, listener, null /* frame */, fromIme,
                listener.getDurationMs(), listener.getInterpolator(),
                show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
                show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN,
+35 −12
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.view.InsetsSourceControlProto.POSITION;
import static android.view.InsetsSourceControlProto.TYPE;

import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Point;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,13 +42,19 @@ public class InsetsSourceControl implements Parcelable {
    private final @InternalInsetsType int mType;
    private final @Nullable SurfaceControl mLeash;
    private final Point mSurfacePosition;

    // This is used while playing an insets animation regardless of the relative frame. This would
    // be the insets received by the bounds of its source window.
    private Insets mInsetsHint;

    private boolean mSkipAnimationOnce;

    public InsetsSourceControl(@InternalInsetsType int type, @Nullable SurfaceControl leash,
            Point surfacePosition) {
            Point surfacePosition, Insets insetsHint) {
        mType = type;
        mLeash = leash;
        mSurfacePosition = surfacePosition;
        mInsetsHint = insetsHint;
    }

    public InsetsSourceControl(InsetsSourceControl other) {
@@ -58,9 +65,18 @@ public class InsetsSourceControl implements Parcelable {
            mLeash = null;
        }
        mSurfacePosition = new Point(other.mSurfacePosition);
        mInsetsHint = other.mInsetsHint;
        mSkipAnimationOnce = other.getAndClearSkipAnimationOnce();
    }

    public InsetsSourceControl(Parcel in) {
        mType = in.readInt();
        mLeash = in.readTypedObject(SurfaceControl.CREATOR);
        mSurfacePosition = in.readTypedObject(Point.CREATOR);
        mInsetsHint = in.readTypedObject(Insets.CREATOR);
        mSkipAnimationOnce = in.readBoolean();
    }

    public int getType() {
        return mType;
    }
@@ -75,13 +91,6 @@ public class InsetsSourceControl implements Parcelable {
        return mLeash;
    }

    public InsetsSourceControl(Parcel in) {
        mType = in.readInt();
        mLeash = in.readTypedObject(SurfaceControl.CREATOR);
        mSurfacePosition = in.readTypedObject(Point.CREATOR);
        mSkipAnimationOnce = in.readBoolean();
    }

    public boolean setSurfacePosition(int left, int top) {
        if (mSurfacePosition.equals(left, top)) {
            return false;
@@ -90,14 +99,26 @@ public class InsetsSourceControl implements Parcelable {
        return true;
    }

    public void setSkipAnimationOnce(boolean skipAnimation) {
        mSkipAnimationOnce = skipAnimation;
    }

    public Point getSurfacePosition() {
        return mSurfacePosition;
    }

    public void setInsetsHint(Insets insets) {
        mInsetsHint = insets;
    }

    public void setInsetsHint(int left, int top, int right, int bottom) {
        mInsetsHint = Insets.of(left, top, right, bottom);
    }

    public Insets getInsetsHint() {
        return mInsetsHint;
    }

    public void setSkipAnimationOnce(boolean skipAnimation) {
        mSkipAnimationOnce = skipAnimation;
    }

    /**
     * Get the state whether the current control needs to skip animation or not.
     *
@@ -121,6 +142,7 @@ public class InsetsSourceControl implements Parcelable {
        dest.writeInt(mType);
        dest.writeTypedObject(mLeash, 0 /* parcelableFlags */);
        dest.writeTypedObject(mSurfacePosition, 0 /* parcelableFlags */);
        dest.writeTypedObject(mInsetsHint, 0 /* parcelableFlags */);
        dest.writeBoolean(mSkipAnimationOnce);
    }

@@ -135,6 +157,7 @@ public class InsetsSourceControl implements Parcelable {
        pw.print("InsetsSourceControl type="); pw.print(InsetsState.typeToString(mType));
        pw.print(" mLeash="); pw.print(mLeash);
        pw.print(" mSurfacePosition="); pw.print(mSurfacePosition);
        pw.print(" mInsetsHint="); pw.print(mInsetsHint);
        pw.print(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce);
        pw.println();
    }
Loading