Loading core/java/android/view/InsetsController.java +18 −1 Original line number Diff line number Diff line Loading @@ -1334,6 +1334,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) { // TODO(b/166736352): We should only skip the animation of specific types, not all types. boolean skipAnim = false; if ((types & ime()) != 0) { final InsetsSourceConsumer consumer = mSourceConsumers.get(ITYPE_IME); final InsetsSourceControl imeControl = consumer != null ? consumer.getControl() : null; // Skip showing animation once that made by system for some reason. // (e.g. starting window with IME snapshot) if (imeControl != null && show) { skipAnim = imeControl.getAndClearSkipAnimationOnce(); } } applyAnimation(types, show, fromIme, skipAnim); } @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme, boolean skipAnim) { if (types == 0) { // nothing to animate. if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate"); Loading @@ -1342,7 +1359,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); final InternalAnimationControlListener listener = new InternalAnimationControlListener( show, hasAnimationCallbacks, types, mAnimationsDisabled, 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 Loading core/java/android/view/InsetsSourceControl.java +22 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ public class InsetsSourceControl implements Parcelable { private final @InternalInsetsType int mType; private final @Nullable SurfaceControl mLeash; private final Point mSurfacePosition; private boolean mSkipAnimationOnce; public InsetsSourceControl(@InternalInsetsType int type, @Nullable SurfaceControl leash, Point surfacePosition) { Loading @@ -57,6 +58,7 @@ public class InsetsSourceControl implements Parcelable { mLeash = null; } mSurfacePosition = new Point(other.mSurfacePosition); mSkipAnimationOnce = other.getAndClearSkipAnimationOnce(); } public int getType() { Loading @@ -77,6 +79,7 @@ public class InsetsSourceControl implements Parcelable { mType = in.readInt(); mLeash = in.readParcelable(null /* loader */); mSurfacePosition = in.readParcelable(null /* loader */); mSkipAnimationOnce = in.readBoolean(); } public boolean setSurfacePosition(int left, int top) { Loading @@ -87,10 +90,27 @@ public class InsetsSourceControl implements Parcelable { return true; } public void setSkipAnimationOnce(boolean skipAnimation) { mSkipAnimationOnce = skipAnimation; } public Point getSurfacePosition() { return mSurfacePosition; } /** * Get the state whether the current control needs to skip animation or not. * * Note that this is a one-time check that the state is only valid and can be called when * {@link InsetsController#applyAnimation} to check if the current control can skip animation * at this time, and then will clear the state value. */ public boolean getAndClearSkipAnimationOnce() { final boolean result = mSkipAnimationOnce; mSkipAnimationOnce = false; return result; } @Override public int describeContents() { return 0; Loading @@ -101,6 +121,7 @@ public class InsetsSourceControl implements Parcelable { dest.writeInt(mType); dest.writeParcelable(mLeash, 0 /* flags*/); dest.writeParcelable(mSurfacePosition, 0 /* flags*/); dest.writeBoolean(mSkipAnimationOnce); } public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) { Loading @@ -114,6 +135,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(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce); pw.println(); } Loading core/java/android/window/TaskSnapshot.java +29 −11 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ public class TaskSnapshot implements Parcelable { private final @WindowInsetsController.Appearance int mAppearance; private final boolean mIsTranslucent; private final boolean mHasImeSurface; // Must be one of the named color spaces, otherwise, always use SRGB color space. private final ColorSpace mColorSpace; Loading @@ -68,7 +69,7 @@ public class TaskSnapshot implements Parcelable { @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize, Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot, int windowingMode, @WindowInsetsController.Appearance int appearance, boolean isTranslucent) { boolean isTranslucent, boolean hasImeSurface) { mId = id; mTopActivityComponent = topActivityComponent; mSnapshot = snapshot; Loading @@ -83,6 +84,7 @@ public class TaskSnapshot implements Parcelable { mWindowingMode = windowingMode; mAppearance = appearance; mIsTranslucent = isTranslucent; mHasImeSurface = hasImeSurface; } private TaskSnapshot(Parcel source) { Loading @@ -102,6 +104,7 @@ public class TaskSnapshot implements Parcelable { mWindowingMode = source.readInt(); mAppearance = source.readInt(); mIsTranslucent = source.readBoolean(); mHasImeSurface = source.readBoolean(); } /** Loading Loading @@ -200,6 +203,13 @@ public class TaskSnapshot implements Parcelable { return mIsTranslucent; } /** * @return Whether or not the snapshot has the IME surface. */ public boolean hasImeSurface() { return mHasImeSurface; } /** * @return The windowing mode of the task when this snapshot was taken. */ Loading Loading @@ -237,6 +247,7 @@ public class TaskSnapshot implements Parcelable { dest.writeInt(mWindowingMode); dest.writeInt(mAppearance); dest.writeBoolean(mIsTranslucent); dest.writeBoolean(mHasImeSurface); } @Override Loading @@ -256,7 +267,8 @@ public class TaskSnapshot implements Parcelable { + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode + " mAppearance=" + mAppearance + " mIsTranslucent=" + mIsTranslucent; + " mIsTranslucent=" + mIsTranslucent + " mHasImeSurface=" + mHasImeSurface; } public static final @NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() { Loading @@ -283,6 +295,7 @@ public class TaskSnapshot implements Parcelable { private @WindowInsetsController.Appearance int mAppearance; private boolean mIsTranslucent; private boolean mHasImeSurface; private int mPixelFormat; public Builder setId(long id) { Loading @@ -290,8 +303,7 @@ public class TaskSnapshot implements Parcelable { return this; } public Builder setTopActivityComponent( ComponentName name) { public Builder setTopActivityComponent(ComponentName name) { mTopActivity = name; return this; } Loading Loading @@ -329,8 +341,7 @@ public class TaskSnapshot implements Parcelable { return this; } public Builder setIsRealSnapshot( boolean realSnapshot) { public Builder setIsRealSnapshot(boolean realSnapshot) { mIsRealSnapshot = realSnapshot; return this; } Loading @@ -340,18 +351,24 @@ public class TaskSnapshot implements Parcelable { return this; } public Builder setAppearance( @WindowInsetsController.Appearance int appearance) { public Builder setAppearance(@WindowInsetsController.Appearance int appearance) { mAppearance = appearance; return this; } public Builder setIsTranslucent( boolean isTranslucent) { public Builder setIsTranslucent(boolean isTranslucent) { mIsTranslucent = isTranslucent; return this; } /** * Sets the IME visibility when taking the snapshot of the task. */ public Builder setHasImeSurface(boolean hasImeSurface) { mHasImeSurface = hasImeSurface; return this; } public int getPixelFormat() { return mPixelFormat; } Loading @@ -378,7 +395,8 @@ public class TaskSnapshot implements Parcelable { mIsRealSnapshot, mWindowingMode, mAppearance, mIsTranslucent); mIsTranslucent, mHasImeSurface); } } Loading core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +22 −0 Original line number Diff line number Diff line Loading @@ -128,4 +128,26 @@ public class ImeInsetsSourceConsumerTest { eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(true) /* fromIme */); }); } @Test public void testImeGetAndClearSkipAnimationOnce() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { // Request IME visible before control is available. mImeConsumer.onWindowFocusGained(); mImeConsumer.applyImeVisibility(true /* setVisible */); // set control and verify visibility is applied. InsetsSourceControl control = Mockito.spy( new InsetsSourceControl(ITYPE_IME, mLeash, new Point())); // Simulate IME source control set this flag when the target has starting window. control.setSkipAnimationOnce(true); mController.onControlsChanged(new InsetsSourceControl[] { control }); // Verify IME show animation should be triggered when control becomes available and // the animation will be skipped by getAndClearSkipAnimationOnce invoked. verify(control).getAndClearSkipAnimationOnce(); verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, eq(true) /* skipAnim */); }); } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ public class TaskSnapshotWindowTest { ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, Surface.ROTATION_0, taskSize, contentInsets, false, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */); 0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */); } private static TaskDescription createTaskDescription(int background, int statusBar, Loading Loading
core/java/android/view/InsetsController.java +18 −1 Original line number Diff line number Diff line Loading @@ -1334,6 +1334,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) { // TODO(b/166736352): We should only skip the animation of specific types, not all types. boolean skipAnim = false; if ((types & ime()) != 0) { final InsetsSourceConsumer consumer = mSourceConsumers.get(ITYPE_IME); final InsetsSourceControl imeControl = consumer != null ? consumer.getControl() : null; // Skip showing animation once that made by system for some reason. // (e.g. starting window with IME snapshot) if (imeControl != null && show) { skipAnim = imeControl.getAndClearSkipAnimationOnce(); } } applyAnimation(types, show, fromIme, skipAnim); } @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme, boolean skipAnim) { if (types == 0) { // nothing to animate. if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate"); Loading @@ -1342,7 +1359,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); final InternalAnimationControlListener listener = new InternalAnimationControlListener( show, hasAnimationCallbacks, types, mAnimationsDisabled, 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 Loading
core/java/android/view/InsetsSourceControl.java +22 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ public class InsetsSourceControl implements Parcelable { private final @InternalInsetsType int mType; private final @Nullable SurfaceControl mLeash; private final Point mSurfacePosition; private boolean mSkipAnimationOnce; public InsetsSourceControl(@InternalInsetsType int type, @Nullable SurfaceControl leash, Point surfacePosition) { Loading @@ -57,6 +58,7 @@ public class InsetsSourceControl implements Parcelable { mLeash = null; } mSurfacePosition = new Point(other.mSurfacePosition); mSkipAnimationOnce = other.getAndClearSkipAnimationOnce(); } public int getType() { Loading @@ -77,6 +79,7 @@ public class InsetsSourceControl implements Parcelable { mType = in.readInt(); mLeash = in.readParcelable(null /* loader */); mSurfacePosition = in.readParcelable(null /* loader */); mSkipAnimationOnce = in.readBoolean(); } public boolean setSurfacePosition(int left, int top) { Loading @@ -87,10 +90,27 @@ public class InsetsSourceControl implements Parcelable { return true; } public void setSkipAnimationOnce(boolean skipAnimation) { mSkipAnimationOnce = skipAnimation; } public Point getSurfacePosition() { return mSurfacePosition; } /** * Get the state whether the current control needs to skip animation or not. * * Note that this is a one-time check that the state is only valid and can be called when * {@link InsetsController#applyAnimation} to check if the current control can skip animation * at this time, and then will clear the state value. */ public boolean getAndClearSkipAnimationOnce() { final boolean result = mSkipAnimationOnce; mSkipAnimationOnce = false; return result; } @Override public int describeContents() { return 0; Loading @@ -101,6 +121,7 @@ public class InsetsSourceControl implements Parcelable { dest.writeInt(mType); dest.writeParcelable(mLeash, 0 /* flags*/); dest.writeParcelable(mSurfacePosition, 0 /* flags*/); dest.writeBoolean(mSkipAnimationOnce); } public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) { Loading @@ -114,6 +135,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(" mSkipAnimationOnce="); pw.print(mSkipAnimationOnce); pw.println(); } Loading
core/java/android/window/TaskSnapshot.java +29 −11 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ public class TaskSnapshot implements Parcelable { private final @WindowInsetsController.Appearance int mAppearance; private final boolean mIsTranslucent; private final boolean mHasImeSurface; // Must be one of the named color spaces, otherwise, always use SRGB color space. private final ColorSpace mColorSpace; Loading @@ -68,7 +69,7 @@ public class TaskSnapshot implements Parcelable { @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize, Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot, int windowingMode, @WindowInsetsController.Appearance int appearance, boolean isTranslucent) { boolean isTranslucent, boolean hasImeSurface) { mId = id; mTopActivityComponent = topActivityComponent; mSnapshot = snapshot; Loading @@ -83,6 +84,7 @@ public class TaskSnapshot implements Parcelable { mWindowingMode = windowingMode; mAppearance = appearance; mIsTranslucent = isTranslucent; mHasImeSurface = hasImeSurface; } private TaskSnapshot(Parcel source) { Loading @@ -102,6 +104,7 @@ public class TaskSnapshot implements Parcelable { mWindowingMode = source.readInt(); mAppearance = source.readInt(); mIsTranslucent = source.readBoolean(); mHasImeSurface = source.readBoolean(); } /** Loading Loading @@ -200,6 +203,13 @@ public class TaskSnapshot implements Parcelable { return mIsTranslucent; } /** * @return Whether or not the snapshot has the IME surface. */ public boolean hasImeSurface() { return mHasImeSurface; } /** * @return The windowing mode of the task when this snapshot was taken. */ Loading Loading @@ -237,6 +247,7 @@ public class TaskSnapshot implements Parcelable { dest.writeInt(mWindowingMode); dest.writeInt(mAppearance); dest.writeBoolean(mIsTranslucent); dest.writeBoolean(mHasImeSurface); } @Override Loading @@ -256,7 +267,8 @@ public class TaskSnapshot implements Parcelable { + " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode + " mAppearance=" + mAppearance + " mIsTranslucent=" + mIsTranslucent; + " mIsTranslucent=" + mIsTranslucent + " mHasImeSurface=" + mHasImeSurface; } public static final @NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() { Loading @@ -283,6 +295,7 @@ public class TaskSnapshot implements Parcelable { private @WindowInsetsController.Appearance int mAppearance; private boolean mIsTranslucent; private boolean mHasImeSurface; private int mPixelFormat; public Builder setId(long id) { Loading @@ -290,8 +303,7 @@ public class TaskSnapshot implements Parcelable { return this; } public Builder setTopActivityComponent( ComponentName name) { public Builder setTopActivityComponent(ComponentName name) { mTopActivity = name; return this; } Loading Loading @@ -329,8 +341,7 @@ public class TaskSnapshot implements Parcelable { return this; } public Builder setIsRealSnapshot( boolean realSnapshot) { public Builder setIsRealSnapshot(boolean realSnapshot) { mIsRealSnapshot = realSnapshot; return this; } Loading @@ -340,18 +351,24 @@ public class TaskSnapshot implements Parcelable { return this; } public Builder setAppearance( @WindowInsetsController.Appearance int appearance) { public Builder setAppearance(@WindowInsetsController.Appearance int appearance) { mAppearance = appearance; return this; } public Builder setIsTranslucent( boolean isTranslucent) { public Builder setIsTranslucent(boolean isTranslucent) { mIsTranslucent = isTranslucent; return this; } /** * Sets the IME visibility when taking the snapshot of the task. */ public Builder setHasImeSurface(boolean hasImeSurface) { mHasImeSurface = hasImeSurface; return this; } public int getPixelFormat() { return mPixelFormat; } Loading @@ -378,7 +395,8 @@ public class TaskSnapshot implements Parcelable { mIsRealSnapshot, mWindowingMode, mAppearance, mIsTranslucent); mIsTranslucent, mHasImeSurface); } } Loading
core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +22 −0 Original line number Diff line number Diff line Loading @@ -128,4 +128,26 @@ public class ImeInsetsSourceConsumerTest { eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(true) /* fromIme */); }); } @Test public void testImeGetAndClearSkipAnimationOnce() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { // Request IME visible before control is available. mImeConsumer.onWindowFocusGained(); mImeConsumer.applyImeVisibility(true /* setVisible */); // set control and verify visibility is applied. InsetsSourceControl control = Mockito.spy( new InsetsSourceControl(ITYPE_IME, mLeash, new Point())); // Simulate IME source control set this flag when the target has starting window. control.setSkipAnimationOnce(true); mController.onControlsChanged(new InsetsSourceControl[] { control }); // Verify IME show animation should be triggered when control becomes available and // the animation will be skipped by getAndClearSkipAnimationOnce invoked. verify(control).getAndClearSkipAnimationOnce(); verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, eq(true) /* skipAnim */); }); } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ public class TaskSnapshotWindowTest { ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, Surface.ROTATION_0, taskSize, contentInsets, false, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */); 0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */); } private static TaskDescription createTaskDescription(int background, int statusBar, Loading