diff options
| -rw-r--r-- | core/java/android/view/ImeInsetsSourceConsumer.java | 68 | ||||
| -rw-r--r-- | core/java/android/view/InsetsController.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/InsetsSourceConsumer.java | 33 | ||||
| -rw-r--r-- | core/proto/android/view/imeinsetssourceconsumer.proto | 5 | ||||
| -rw-r--r-- | core/proto/android/view/insetssourceconsumer.proto | 1 |
5 files changed, 74 insertions, 45 deletions
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index f87b746fa72e..f06ba3b422df 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -17,10 +17,9 @@ package android.view; import static android.os.Trace.TRACE_TAG_VIEW; +import static android.view.ImeInsetsSourceConsumerProto.HAS_PENDING_REQUEST; import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER; -import static android.view.ImeInsetsSourceConsumerProto.IS_HIDE_ANIMATION_RUNNING; import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL; -import static android.view.ImeInsetsSourceConsumerProto.IS_SHOW_REQUESTED_DURING_HIDE_ANIMATION; import android.annotation.Nullable; import android.os.IBinder; @@ -43,20 +42,16 @@ import java.util.function.Supplier; public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { /** - * Tracks whether we have an outstanding request from the IME to show, but weren't able to - * execute it because we didn't have control yet. + * Tracks whether are requested to show during the hide animation or requested to hide during + * the show animation. If this is true, we should not remove the surface. */ - private boolean mIsRequestedVisibleAwaitingControl; - - private boolean mIsHideAnimationRunning; + private boolean mHasPendingRequest; /** - * Tracks whether {@link WindowInsetsController#show(int)} or - * {@link InputMethodManager#showSoftInput(View, int)} is called during IME hide animation. - * If it was called, we should not call {@link InputMethodManager#notifyImeHidden(IBinder, - * ImeTracker.Token)}, because the IME is being shown. + * Tracks whether we have an outstanding request from the IME to show, but weren't able to + * execute it because we didn't have control yet. */ - private boolean mIsShowRequestedDuringHideAnimation; + private boolean mIsRequestedVisibleAwaitingControl; public ImeInsetsSourceConsumer( int id, InsetsState state, Supplier<Transaction> transactionSupplier, @@ -72,27 +67,19 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { mController.getHost().getInputMethodManager(), null /* icProto */); } final boolean insetsChanged = super.onAnimationStateChanged(running); - final boolean showRequested = (mController.getRequestedVisibleTypes() & getType()) != 0; - if (showRequested) { - onShowRequested(); - } else { + if (!isShowRequested()) { mIsRequestedVisibleAwaitingControl = false; - if (!running) { - // Remove IME surface as IME has finished hide animation, if there is no pending - // show request. - if (!mIsShowRequestedDuringHideAnimation) { - notifyHidden(null /* statsToken */); - removeSurface(); - } + if (!running && !mHasPendingRequest) { + notifyHidden(null /* statsToken */); + removeSurface(); } - // Here is reached - // (1) before the hide animation starts. - // (2) after the hide animation ends. - // (3) if the IME is not controllable (animationFinished == true in this case). - // We should reset mIsShowRequestedDuringHideAnimation in all cases. - mIsHideAnimationRunning = running; - mIsShowRequestedDuringHideAnimation = false; } + // This method is called + // (1) after the animation starts. + // (2) after the animation ends (including the case of cancel). + // (3) if the IME is not controllable (running == false in this case). + // We should reset mHasPendingRequest in all cases. + mHasPendingRequest = false; return insetsChanged; } @@ -132,6 +119,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { "ImeInsetsSourceConsumer#requestShow", mController.getHost().getInputMethodManager(), null /* icProto */); } + onShowRequested(); // TODO: ResultReceiver for IME. // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag. @@ -153,6 +141,17 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED; } + void requestHide(boolean fromIme, @Nullable ImeTracker.Token statsToken) { + if (!fromIme) { + // The insets might be controlled by a remote target. Let the server know we are + // requested to hide. + notifyHidden(statsToken); + } + if (mAnimationState == ANIMATION_STATE_SHOW) { + mHasPendingRequest = true; + } + } + /** * Notify {@link com.android.server.inputmethod.InputMethodManagerService} that * IME insets are hidden. @@ -222,18 +221,17 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { final long token = proto.start(fieldId); super.dumpDebug(proto, INSETS_SOURCE_CONSUMER); proto.write(IS_REQUESTED_VISIBLE_AWAITING_CONTROL, mIsRequestedVisibleAwaitingControl); - proto.write(IS_HIDE_ANIMATION_RUNNING, mIsHideAnimationRunning); - proto.write(IS_SHOW_REQUESTED_DURING_HIDE_ANIMATION, mIsShowRequestedDuringHideAnimation); + proto.write(HAS_PENDING_REQUEST, mHasPendingRequest); proto.end(token); } /** - * Called when {@link #onAnimationStateChanged(boolean)} or + * Called when {@link #requestShow(boolean, ImeTracker.Token)} or * {@link InputMethodManager#showSoftInput(View, int)} is called. */ public void onShowRequested() { - if (mIsHideAnimationRunning) { - mIsShowRequestedDuringHideAnimation = true; + if (mAnimationState == ANIMATION_STATE_HIDE) { + mHasPendingRequest = true; } } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 8abe66afae4d..829321e3652b 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -1203,8 +1203,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return; } ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_DISABLED_USER_ANIMATION); - - cancelExistingControllers(types); if (DEBUG) Log.d(TAG, "controlAnimation types: " + types); mLastStartedAnimTypes |= types; @@ -1236,9 +1234,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation }); } - // The requested visibilities should be delayed as well. Otherwise, the server will - // create already visible leashes for us before we play the show animation. - setRequestedVisibleTypes(mReportedRequestedVisibleTypes, types); + // The requested visibilities should be delayed as well. Otherwise, we might override + // the insets visibility before playing animation. + setRequestedVisibleTypes(mReportedRequestedVisibleTypes, typesReady); Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0); if (!fromIme) { @@ -1250,7 +1248,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (typesReady == 0) { if (DEBUG) Log.d(TAG, "No types ready. onCancelled()"); listener.onCancelled(null); - reportRequestedVisibleTypes(); Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0); if (!fromIme) { Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0); @@ -1258,6 +1255,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return; } + cancelExistingControllers(typesReady); final InsetsAnimationControlRunner runner = useInsetsAnimationThread ? new InsetsAnimationThreadControlRunner(controls, @@ -1344,6 +1342,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation setRequestedVisibleTypes(0 /* visibleTypes */, consumer.getType()); break; } + } else { + consumer.requestHide(fromIme, statsToken); } if (!canRun) { if (WARN) Log.w(TAG, String.format( diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index 47672a3ec18e..467d720196b1 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -19,6 +19,7 @@ package android.view; import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.AnimationType; import static android.view.InsetsController.DEBUG; +import static android.view.InsetsSourceConsumerProto.ANIMATION_STATE; import static android.view.InsetsSourceConsumerProto.HAS_WINDOW_FOCUS; import static android.view.InsetsSourceConsumerProto.INTERNAL_INSETS_TYPE; import static android.view.InsetsSourceConsumerProto.IS_REQUESTED_VISIBLE; @@ -73,6 +74,12 @@ public class InsetsSourceConsumer { int IME_SHOW_FAILED = 2; } + protected static final int ANIMATION_STATE_NONE = 0; + protected static final int ANIMATION_STATE_SHOW = 1; + protected static final int ANIMATION_STATE_HIDE = 2; + + protected int mAnimationState = ANIMATION_STATE_NONE; + protected final InsetsController mController; protected final InsetsState mState; private int mId; @@ -230,14 +237,31 @@ public class InsetsSourceConsumer { mPendingVisibleFrame = null; } + final boolean showRequested = isShowRequested(); + final boolean cancelledForNewAnimation = !running && showRequested + ? mAnimationState == ANIMATION_STATE_HIDE + : mAnimationState == ANIMATION_STATE_SHOW; + + mAnimationState = running + ? (showRequested ? ANIMATION_STATE_SHOW : ANIMATION_STATE_HIDE) + : ANIMATION_STATE_NONE; + // We apply the visibility override after the animation is started. We don't do this before // that because we need to know the initial insets state while creating the animation. // We also need to apply the override after the animation is finished because the requested // visibility can be set when finishing the user animation. - insetsChanged |= applyLocalVisibilityOverride(); + // If the animation is cancelled because we are going to play a new animation with an + // opposite direction, don't apply it now but after the new animation is started. + if (!cancelledForNewAnimation) { + insetsChanged |= applyLocalVisibilityOverride(); + } return insetsChanged; } + protected boolean isShowRequested() { + return (mController.getRequestedVisibleTypes() & getType()) != 0; + } + /** * Called when current window gains focus */ @@ -300,6 +324,10 @@ public class InsetsSourceConsumer { return ShowResult.SHOW_IMMEDIATELY; } + void requestHide(boolean fromController, @Nullable ImeTracker.Token statsToken) { + // no-op for types that always return ShowResult#SHOW_IMMEDIATELY. + } + /** * Reports that this source's perceptibility has changed * @@ -364,7 +392,7 @@ public class InsetsSourceConsumer { final long token = proto.start(fieldId); proto.write(INTERNAL_INSETS_TYPE, WindowInsets.Type.toString(mType)); proto.write(HAS_WINDOW_FOCUS, mHasWindowFocus); - proto.write(IS_REQUESTED_VISIBLE, (mController.getRequestedVisibleTypes() & mType) != 0); + proto.write(IS_REQUESTED_VISIBLE, isShowRequested()); if (mSourceControl != null) { mSourceControl.dumpDebug(proto, SOURCE_CONTROL); } @@ -374,6 +402,7 @@ public class InsetsSourceConsumer { if (mPendingVisibleFrame != null) { mPendingVisibleFrame.dumpDebug(proto, PENDING_VISIBLE_FRAME); } + proto.write(ANIMATION_STATE, mAnimationState); proto.end(token); } } diff --git a/core/proto/android/view/imeinsetssourceconsumer.proto b/core/proto/android/view/imeinsetssourceconsumer.proto index 6e007fad5f8d..a85f6936d252 100644 --- a/core/proto/android/view/imeinsetssourceconsumer.proto +++ b/core/proto/android/view/imeinsetssourceconsumer.proto @@ -29,6 +29,7 @@ message ImeInsetsSourceConsumerProto { optional InsetsSourceConsumerProto insets_source_consumer = 1; reserved 2; // focused_editor = 2 optional bool is_requested_visible_awaiting_control = 3; - optional bool is_hide_animation_running = 4; - optional bool is_show_requested_during_hide_animation = 5; + optional bool is_hide_animation_running = 4 [deprecated=true]; + optional bool is_show_requested_during_hide_animation = 5 [deprecated=true]; + optional bool has_pending_request = 6; }
\ No newline at end of file diff --git a/core/proto/android/view/insetssourceconsumer.proto b/core/proto/android/view/insetssourceconsumer.proto index 487e06c1ccdf..a01ad8eea582 100644 --- a/core/proto/android/view/insetssourceconsumer.proto +++ b/core/proto/android/view/insetssourceconsumer.proto @@ -33,4 +33,5 @@ message InsetsSourceConsumerProto { optional InsetsSourceControlProto source_control = 4; optional .android.graphics.RectProto pending_frame = 5; optional .android.graphics.RectProto pending_visible_frame = 6; + optional int32 animation_state = 7; }
\ No newline at end of file |