Fix WIC#hide(ime()) no-op after WIC#show(ime()) in Activity#onCreate

In InsetsController#hide, ensure to request hide IME with calling
ImeInsetsSurceConsumer#requestHide, in case the pending visible
request will triggger show after setControl.

Also, we modified PendingControlRequest to be able to remove from the
show insets type when it has being requested invisible by
InsetsController#hide(type), if the removed type contains the IME then
we handle the pending show control request for other types since it
is no longer needed to wait the IME ready to show.

Also, make sure set mIsRequestedVisibleAwaitingControl as false when
ImeInsetsSourceConsumer#notifyHidden to avoid the above pending visible
request happens.

Bug: 248456059
Test: atest CtsInputMethodTestCases
Test: atest InputMethodStressTest:ImeOpenCloseStressTest
Change-Id: Id3aebca3348888826bc5d3c6694e94cddb80b4d4
This commit is contained in:
Ming-Shin Lu
2022-12-29 06:00:20 +00:00
parent 0b6a420958
commit 737c79151c
2 changed files with 48 additions and 14 deletions

View File

@@ -173,6 +173,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
ImeTracker.PHASE_CLIENT_INSETS_CONSUMER_NOTIFY_HIDDEN);
getImm().notifyImeHidden(mController.getHost().getWindowToken(), statsToken);
mIsRequestedVisibleAwaitingControl = false;
Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
}

View File

@@ -552,7 +552,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
this.useInsetsAnimationThread = useInsetsAnimationThread;
}
final @InsetsType int types;
@InsetsType int types;
final WindowInsetsAnimationControlListener listener;
final long durationMs;
final Interpolator interpolator;
@@ -1006,19 +1006,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
// Handle pending request ready in case there was one set.
if (fromIme && mPendingImeControlRequest != null) {
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, null /* frame */,
true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
pendingRequest.animationType,
pendingRequest.layoutInsetsDuringAnimation,
pendingRequest.useInsetsAnimationThread, statsToken);
handlePendingControlRequest(statsToken);
return;
}
@@ -1061,6 +1049,27 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
applyAnimation(typesReady, true /* show */, fromIme, statsToken);
}
/**
* Handle the {@link #mPendingImeControlRequest} when
* - The IME insets is ready to show.
* - The IME insets has being requested invisible.
*/
private void handlePendingControlRequest(@Nullable ImeTracker.Token statsToken) {
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, null /* frame */,
true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
pendingRequest.animationType,
pendingRequest.layoutInsetsDuringAnimation,
pendingRequest.useInsetsAnimationThread, statsToken);
}
@Override
public void hide(@InsetsType int types) {
ImeTracker.Token statsToken = null;
@@ -1084,6 +1093,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
}
int typesReady = 0;
boolean hasImeRequestedHidden = false;
final boolean hadPendingImeControlRequest = mPendingImeControlRequest != null;
for (int type = FIRST; type <= LAST; type = type << 1) {
if ((types & type) == 0) {
continue;
@@ -1091,6 +1102,22 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@AnimationType final int animationType = getAnimationType(type);
final boolean requestedVisible = (type & mRequestedVisibleTypes) != 0;
final boolean isImeAnimation = type == ime();
if (mPendingImeControlRequest != null && !requestedVisible) {
// Remove the hide insets type from the pending show request.
mPendingImeControlRequest.types &= ~type;
if (mPendingImeControlRequest.types == 0) {
abortPendingImeControlRequest();
}
}
if (isImeAnimation && !requestedVisible && animationType == ANIMATION_TYPE_NONE) {
hasImeRequestedHidden = true;
// Ensure to request hide IME in case there is any pending requested visible
// being applied from setControl when receiving the insets control.
if (hadPendingImeControlRequest
|| getImeSourceConsumer().isRequestedVisibleAwaitingControl()) {
getImeSourceConsumer().requestHide(fromIme, statsToken);
}
}
if (!requestedVisible && animationType == ANIMATION_TYPE_NONE
|| animationType == ANIMATION_TYPE_HIDE) {
// no-op: already hidden or animating out (because window visibility is
@@ -1106,6 +1133,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
typesReady |= type;
}
if (hasImeRequestedHidden && mPendingImeControlRequest != null) {
// Handle the pending show request for other insets types since the IME insets has being
// requested hidden.
handlePendingControlRequest(statsToken);
getImeSourceConsumer().removeSurface();
}
applyAnimation(typesReady, false /* show */, fromIme, statsToken);
}