Loading core/java/android/content/res/CompatibilityInfo.java +28 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. */ Loading core/java/android/view/InsetsAnimationControlImpl.java +92 −44 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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(); Loading @@ -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) { Loading @@ -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); Loading @@ -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); } } } core/java/android/view/InsetsAnimationThreadControlRunner.java +3 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading core/java/android/view/InsetsController.java +8 −5 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading core/java/android/view/InsetsSourceControl.java +35 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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; } Loading @@ -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; Loading @@ -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. * Loading @@ -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); } Loading @@ -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 Loading
core/java/android/content/res/CompatibilityInfo.java +28 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. */ Loading
core/java/android/view/InsetsAnimationControlImpl.java +92 −44 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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(); Loading @@ -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) { Loading @@ -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); Loading @@ -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); } } }
core/java/android/view/InsetsAnimationThreadControlRunner.java +3 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading
core/java/android/view/InsetsController.java +8 −5 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading
core/java/android/view/InsetsSourceControl.java +35 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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; } Loading @@ -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; Loading @@ -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. * Loading @@ -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); } Loading @@ -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