Loading core/java/android/view/ImeInsetsSourceConsumer.java +3 −3 Original line number Diff line number Diff line Loading @@ -221,13 +221,13 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes, int[] cancelTypes) { int[] hideTypes, int[] cancelTypes, int[] transientTypes) { if (Flags.refactorInsetsController()) { return super.setControl(control, showTypes, hideTypes, cancelTypes); return super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } else { ImeTracing.getInstance().triggerClientDump("ImeInsetsSourceConsumer#setControl", mController.getHost().getInputMethodManager(), null /* icProto */); if (!super.setControl(control, showTypes, hideTypes, cancelTypes)) { if (!super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes)) { return false; } if (control == null && !mIsRequestedVisibleAwaitingLeash) { Loading core/java/android/view/InsetsController.java +32 −17 Original line number Diff line number Diff line Loading @@ -959,6 +959,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final @InsetsType int[] showTypes = new int[1]; final @InsetsType int[] hideTypes = new int[1]; final @InsetsType int[] cancelTypes = new int[1]; final @InsetsType int[] transientTypes = new int[1]; ImeTracker.Token statsToken = null; // Ensure to update all existing source consumers Loading @@ -984,7 +985,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // control may be null, but we still need to update the control to null if it got // revoked. consumer.setControl(control, showTypes, hideTypes, cancelTypes); consumer.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } // Ensure to create source consumers if not available yet. Loading @@ -992,7 +993,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation for (int i = mTmpControlArray.size() - 1; i >= 0; i--) { final InsetsSourceControl control = mTmpControlArray.valueAt(i); getSourceConsumer(control.getId(), control.getType()) .setControl(control, showTypes, hideTypes, cancelTypes); .setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } } Loading Loading @@ -1020,10 +1021,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation handlePendingControlRequest(statsToken); } else { if (showTypes[0] != 0) { applyAnimation(showTypes[0], true /* show */, false /* fromIme */, statsToken); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, false /* skipsCallbacks */, statsToken); } if (hideTypes[0] != 0) { applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, statsToken); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, // The animation of hiding transient types shouldn't be detected by the // app. Otherwise, it might be able to react to the callbacks and cause // flickering. (hideTypes[0] & ~transientTypes[0]) == 0 /* skipsCallbacks */, statsToken); } } } else { Loading @@ -1033,7 +1040,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation ImeTracker.TYPE_SHOW, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, newStatsToken); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, false /* skipsCallbacks */, newStatsToken); } if (hideTypes[0] != 0) { final var newStatsToken = Loading @@ -1041,7 +1049,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, newStatsToken); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, // The animation of hiding transient types shouldn't be detected by the app. // Otherwise, it might be able to react to the callbacks and cause // flickering. (hideTypes[0] & ~transientTypes[0]) == 0 /* skipsCallbacks */, newStatsToken); } } Loading Loading @@ -1174,7 +1187,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // TODO(b/353463205) check if this is needed here ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication); } applyAnimation(typesReady, true /* show */, fromIme, statsToken); applyAnimation(typesReady, true /* show */, fromIme, false /* skipsCallbacks */, statsToken); } /** Loading Loading @@ -1287,7 +1301,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation handlePendingControlRequest(statsToken); getImeSourceConsumer().removeSurface(); } applyAnimation(typesReady, false /* show */, fromIme, statsToken); applyAnimation(typesReady, false /* show */, fromIme, false /* skipsCallbacks */, statsToken); } @Override Loading Loading @@ -2007,24 +2022,24 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme, @Nullable ImeTracker.Token statsToken) { boolean skipsCallbacks, @Nullable ImeTracker.Token statsToken) { // TODO(b/166736352): We should only skip the animation of specific types, not all types. boolean skipAnim = false; boolean skipsAnim = false; if ((types & ime()) != 0) { final InsetsSourceControl imeControl = mImeSourceConsumer.getControl(); // Skip showing animation once that made by system for some reason. // (e.g. starting window with IME snapshot) if (imeControl != null) { skipAnim = imeControl.getAndClearSkipAnimationOnce() && show skipsAnim = imeControl.getAndClearSkipAnimationOnce() && show && mImeSourceConsumer.hasViewFocusWhenWindowFocusGain(); } } applyAnimation(types, show, fromIme, skipAnim, statsToken); applyAnimation(types, show, fromIme, skipsAnim, skipsCallbacks, statsToken); } @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme, boolean skipAnim, @Nullable ImeTracker.Token statsToken) { boolean skipsAnim, boolean skipsCallbacks, @Nullable ImeTracker.Token statsToken) { if (types == 0) { // nothing to animate. if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate. Stopping here"); Loading @@ -2040,7 +2055,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); final InternalAnimationControlListener listener = new InternalAnimationControlListener( show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(), skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP), skipsAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP), mLoggingListener, mJankContext); // We are about to playing the default animation (show/hide). Passing a null frame indicates Loading @@ -2050,7 +2065,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation listener /* insetsAnimationSpec */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN, !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken, !hasAnimationCallbacks || skipsCallbacks /* useInsetsAnimationThread */, statsToken, false /* fromPredictiveBack */); } Loading Loading @@ -2173,12 +2188,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation new InsetsSourceControl(ID_IME_CAPTION_BAR, captionBar(), null /* leash */, false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1], new int[1]); new int[1], new int[1], new int[1], new int[1]); } else { mState.removeSource(ID_IME_CAPTION_BAR); InsetsSourceConsumer sourceConsumer = mSourceConsumers.get(ID_IME_CAPTION_BAR); if (sourceConsumer != null) { sourceConsumer.setControl(null, new int[1], new int[1], new int[1]); sourceConsumer.setControl(null, new int[1], new int[1], new int[1], new int[1]); } } mHost.notifyInsetsChanged(); Loading core/java/android/view/InsetsSourceConsumer.java +7 −1 Original line number Diff line number Diff line Loading @@ -130,7 +130,10 @@ public class InsetsSourceConsumer { * @return Whether the control has changed from the server */ public boolean setControl(@Nullable InsetsSourceControl control, @InsetsType int[] showTypes, @InsetsType int[] hideTypes, int[] cancelTypes) { @InsetsType int[] showTypes, @InsetsType int[] hideTypes, @InsetsType int[] cancelTypes, @InsetsType int[] transientTypes) { if (Objects.equals(mSourceControl, control)) { if (mSourceControl != null && mSourceControl != control) { mSourceControl.release(SurfaceControl::release); Loading Loading @@ -185,6 +188,9 @@ public class InsetsSourceConsumer { } else { hideTypes[0] |= mType; } if (lastControl != null && lastControl.isFake()) { transientTypes[0] |= mType; } } else { // We are gaining control, but don't need to run an animation. // However make sure that the leash visibility is still up to date. Loading core/java/android/view/InsetsSourceControl.java +4 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,10 @@ public class InsetsSourceControl implements Parcelable { return mInsetsHint; } public boolean isFake() { return mLeash == null && Insets.NONE.equals(mInsetsHint); } public void setSkipAnimationOnce(boolean skipAnimation) { mSkipAnimationOnce = skipAnimation; } Loading core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +16 −12 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(statsToken)); eq(false) /* skipsCallbacks */, eq(statsToken)); // set control and verify visibility is applied. InsetsSourceControl control = new InsetsSourceControl(ID_IME, Loading @@ -142,10 +142,10 @@ public class ImeInsetsSourceConsumerTest { // IME show animation should be triggered when control becomes available. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); }); } Loading @@ -163,7 +163,7 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(statsToken)); eq(false) /* skipsCallbacks */, eq(statsToken)); // Clear previous invocations to verify this is never called with control without leash. clearInvocations(mController); Loading @@ -175,10 +175,10 @@ public class ImeInsetsSourceConsumerTest { // as we have no leash. verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); // set control with leash and verify visibility is applied. InsetsSourceControl controlWithLeash = new InsetsSourceControl(ID_IME, Loading @@ -187,10 +187,10 @@ public class ImeInsetsSourceConsumerTest { // IME show animation should be triggered when control with leash becomes available. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); }); } Loading Loading @@ -223,7 +223,8 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation(eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(false) /* skipAnim */, eq(statsToken)); eq(false) /* skipsAnim */, eq(false) /* skipsCallbacks */, eq(statsToken)); } // set control and verify visibility is applied. Loading @@ -241,7 +242,8 @@ public class ImeInsetsSourceConsumerTest { // so the statsToken won't match. verify(mController).applyAnimation(eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, eq(expectSkipAnim) /* skipAnim */, and(not(eq(statsToken)), notNull())); eq(expectSkipAnim) /* skipsAnim */, eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); } // If previously hasViewFocus is false, verify when requesting the IME visible next Loading @@ -252,14 +254,16 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation(eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(false) /* skipAnim */, eq(statsTokenNext)); eq(false) /* skipsAnim */, eq(false) /* skipsCallbacks */, eq(statsTokenNext)); 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 */, and(not(eq(statsToken)), notNull())); eq(true) /* skipsAnim */, eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); } }); } Loading Loading
core/java/android/view/ImeInsetsSourceConsumer.java +3 −3 Original line number Diff line number Diff line Loading @@ -221,13 +221,13 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes, int[] cancelTypes) { int[] hideTypes, int[] cancelTypes, int[] transientTypes) { if (Flags.refactorInsetsController()) { return super.setControl(control, showTypes, hideTypes, cancelTypes); return super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } else { ImeTracing.getInstance().triggerClientDump("ImeInsetsSourceConsumer#setControl", mController.getHost().getInputMethodManager(), null /* icProto */); if (!super.setControl(control, showTypes, hideTypes, cancelTypes)) { if (!super.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes)) { return false; } if (control == null && !mIsRequestedVisibleAwaitingLeash) { Loading
core/java/android/view/InsetsController.java +32 −17 Original line number Diff line number Diff line Loading @@ -959,6 +959,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation final @InsetsType int[] showTypes = new int[1]; final @InsetsType int[] hideTypes = new int[1]; final @InsetsType int[] cancelTypes = new int[1]; final @InsetsType int[] transientTypes = new int[1]; ImeTracker.Token statsToken = null; // Ensure to update all existing source consumers Loading @@ -984,7 +985,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // control may be null, but we still need to update the control to null if it got // revoked. consumer.setControl(control, showTypes, hideTypes, cancelTypes); consumer.setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } // Ensure to create source consumers if not available yet. Loading @@ -992,7 +993,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation for (int i = mTmpControlArray.size() - 1; i >= 0; i--) { final InsetsSourceControl control = mTmpControlArray.valueAt(i); getSourceConsumer(control.getId(), control.getType()) .setControl(control, showTypes, hideTypes, cancelTypes); .setControl(control, showTypes, hideTypes, cancelTypes, transientTypes); } } Loading Loading @@ -1020,10 +1021,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation handlePendingControlRequest(statsToken); } else { if (showTypes[0] != 0) { applyAnimation(showTypes[0], true /* show */, false /* fromIme */, statsToken); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, false /* skipsCallbacks */, statsToken); } if (hideTypes[0] != 0) { applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, statsToken); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, // The animation of hiding transient types shouldn't be detected by the // app. Otherwise, it might be able to react to the callbacks and cause // flickering. (hideTypes[0] & ~transientTypes[0]) == 0 /* skipsCallbacks */, statsToken); } } } else { Loading @@ -1033,7 +1040,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation ImeTracker.TYPE_SHOW, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, newStatsToken); applyAnimation(showTypes[0], true /* show */, false /* fromIme */, false /* skipsCallbacks */, newStatsToken); } if (hideTypes[0] != 0) { final var newStatsToken = Loading @@ -1041,7 +1049,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.CONTROLS_CHANGED, mHost.isHandlingPointerEvent() /* fromUser */); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, newStatsToken); applyAnimation(hideTypes[0], false /* show */, false /* fromIme */, // The animation of hiding transient types shouldn't be detected by the app. // Otherwise, it might be able to react to the callbacks and cause // flickering. (hideTypes[0] & ~transientTypes[0]) == 0 /* skipsCallbacks */, newStatsToken); } } Loading Loading @@ -1174,7 +1187,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // TODO(b/353463205) check if this is needed here ImeTracker.forLatency().onShown(statsToken, ActivityThread::currentApplication); } applyAnimation(typesReady, true /* show */, fromIme, statsToken); applyAnimation(typesReady, true /* show */, fromIme, false /* skipsCallbacks */, statsToken); } /** Loading Loading @@ -1287,7 +1301,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation handlePendingControlRequest(statsToken); getImeSourceConsumer().removeSurface(); } applyAnimation(typesReady, false /* show */, fromIme, statsToken); applyAnimation(typesReady, false /* show */, fromIme, false /* skipsCallbacks */, statsToken); } @Override Loading Loading @@ -2007,24 +2022,24 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme, @Nullable ImeTracker.Token statsToken) { boolean skipsCallbacks, @Nullable ImeTracker.Token statsToken) { // TODO(b/166736352): We should only skip the animation of specific types, not all types. boolean skipAnim = false; boolean skipsAnim = false; if ((types & ime()) != 0) { final InsetsSourceControl imeControl = mImeSourceConsumer.getControl(); // Skip showing animation once that made by system for some reason. // (e.g. starting window with IME snapshot) if (imeControl != null) { skipAnim = imeControl.getAndClearSkipAnimationOnce() && show skipsAnim = imeControl.getAndClearSkipAnimationOnce() && show && mImeSourceConsumer.hasViewFocusWhenWindowFocusGain(); } } applyAnimation(types, show, fromIme, skipAnim, statsToken); applyAnimation(types, show, fromIme, skipsAnim, skipsCallbacks, statsToken); } @VisibleForTesting public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme, boolean skipAnim, @Nullable ImeTracker.Token statsToken) { boolean skipsAnim, boolean skipsCallbacks, @Nullable ImeTracker.Token statsToken) { if (types == 0) { // nothing to animate. if (DEBUG) Log.d(TAG, "applyAnimation, nothing to animate. Stopping here"); Loading @@ -2040,7 +2055,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); final InternalAnimationControlListener listener = new InternalAnimationControlListener( show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(), skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP), skipsAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP), mLoggingListener, mJankContext); // We are about to playing the default animation (show/hide). Passing a null frame indicates Loading @@ -2050,7 +2065,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation listener /* insetsAnimationSpec */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN, !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken, !hasAnimationCallbacks || skipsCallbacks /* useInsetsAnimationThread */, statsToken, false /* fromPredictiveBack */); } Loading Loading @@ -2173,12 +2188,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation new InsetsSourceControl(ID_IME_CAPTION_BAR, captionBar(), null /* leash */, false /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1], new int[1]); new int[1], new int[1], new int[1], new int[1]); } else { mState.removeSource(ID_IME_CAPTION_BAR); InsetsSourceConsumer sourceConsumer = mSourceConsumers.get(ID_IME_CAPTION_BAR); if (sourceConsumer != null) { sourceConsumer.setControl(null, new int[1], new int[1], new int[1]); sourceConsumer.setControl(null, new int[1], new int[1], new int[1], new int[1]); } } mHost.notifyInsetsChanged(); Loading
core/java/android/view/InsetsSourceConsumer.java +7 −1 Original line number Diff line number Diff line Loading @@ -130,7 +130,10 @@ public class InsetsSourceConsumer { * @return Whether the control has changed from the server */ public boolean setControl(@Nullable InsetsSourceControl control, @InsetsType int[] showTypes, @InsetsType int[] hideTypes, int[] cancelTypes) { @InsetsType int[] showTypes, @InsetsType int[] hideTypes, @InsetsType int[] cancelTypes, @InsetsType int[] transientTypes) { if (Objects.equals(mSourceControl, control)) { if (mSourceControl != null && mSourceControl != control) { mSourceControl.release(SurfaceControl::release); Loading Loading @@ -185,6 +188,9 @@ public class InsetsSourceConsumer { } else { hideTypes[0] |= mType; } if (lastControl != null && lastControl.isFake()) { transientTypes[0] |= mType; } } else { // We are gaining control, but don't need to run an animation. // However make sure that the leash visibility is still up to date. Loading
core/java/android/view/InsetsSourceControl.java +4 −0 Original line number Diff line number Diff line Loading @@ -142,6 +142,10 @@ public class InsetsSourceControl implements Parcelable { return mInsetsHint; } public boolean isFake() { return mLeash == null && Insets.NONE.equals(mInsetsHint); } public void setSkipAnimationOnce(boolean skipAnimation) { mSkipAnimationOnce = skipAnimation; } Loading
core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +16 −12 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(statsToken)); eq(false) /* skipsCallbacks */, eq(statsToken)); // set control and verify visibility is applied. InsetsSourceControl control = new InsetsSourceControl(ID_IME, Loading @@ -142,10 +142,10 @@ public class ImeInsetsSourceConsumerTest { // IME show animation should be triggered when control becomes available. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); }); } Loading @@ -163,7 +163,7 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(statsToken)); eq(false) /* skipsCallbacks */, eq(statsToken)); // Clear previous invocations to verify this is never called with control without leash. clearInvocations(mController); Loading @@ -175,10 +175,10 @@ public class ImeInsetsSourceConsumerTest { // as we have no leash. verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); // set control with leash and verify visibility is applied. InsetsSourceControl controlWithLeash = new InsetsSourceControl(ID_IME, Loading @@ -187,10 +187,10 @@ public class ImeInsetsSourceConsumerTest { // IME show animation should be triggered when control with leash becomes available. verify(mController).applyAnimation( eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); verify(mController, never()).applyAnimation( eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(false) /* fromIme */, and(not(eq(statsToken)), notNull())); eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); }); } Loading Loading @@ -223,7 +223,8 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation(eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(false) /* skipAnim */, eq(statsToken)); eq(false) /* skipsAnim */, eq(false) /* skipsCallbacks */, eq(statsToken)); } // set control and verify visibility is applied. Loading @@ -241,7 +242,8 @@ public class ImeInsetsSourceConsumerTest { // so the statsToken won't match. verify(mController).applyAnimation(eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */, eq(expectSkipAnim) /* skipAnim */, and(not(eq(statsToken)), notNull())); eq(expectSkipAnim) /* skipsAnim */, eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); } // If previously hasViewFocus is false, verify when requesting the IME visible next Loading @@ -252,14 +254,16 @@ public class ImeInsetsSourceConsumerTest { // Called once through the show flow. verify(mController).applyAnimation(eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(true) /* fromIme */, eq(false) /* skipAnim */, eq(statsTokenNext)); eq(false) /* skipsAnim */, eq(false) /* skipsCallbacks */, eq(statsTokenNext)); 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 */, and(not(eq(statsToken)), notNull())); eq(true) /* skipsAnim */, eq(false) /* skipsCallbacks */, and(not(eq(statsToken)), notNull())); } }); } Loading