Merge "Fix the logic about notifyImeHidden and removeImeSurface"

This commit is contained in:
Tiger Huang
2022-12-28 12:17:52 +00:00
committed by Android (Google) Code Review
5 changed files with 74 additions and 45 deletions

View File

@@ -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;
@@ -42,22 +41,18 @@ import java.util.function.Supplier;
*/
public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
/**
* 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 mHasPendingRequest;
/**
* 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 mIsRequestedVisibleAwaitingControl;
private boolean mIsHideAnimationRunning;
/**
* 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.
*/
private boolean mIsShowRequestedDuringHideAnimation;
public ImeInsetsSourceConsumer(
int id, InsetsState state, Supplier<Transaction> transactionSupplier,
InsetsController controller) {
@@ -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;
}
}

View File

@@ -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(

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}