Merge changes Ib7baf280,Id3aebca3

* changes:
  Remove TODO in InputMethodStressTest
  Fix WIC#hide(ime()) no-op after WIC#show(ime()) in Activity#onCreate
This commit is contained in:
Ming-Shin Lu
2023-01-07 02:24:25 +00:00
committed by Android (Google) Code Review
3 changed files with 82 additions and 22 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);
}

View File

@@ -16,6 +16,8 @@
package com.android.inputmethod.stresstest;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.INPUT_METHOD_MANAGER_HIDE_ON_CREATE;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.INPUT_METHOD_MANAGER_SHOW_ON_CREATE;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.REQUEST_FOCUS_ON_CREATE;
@@ -209,8 +211,23 @@ public final class ImeOpenCloseStressTest {
verifyShowBehavior(activity);
}
/**
* Test IME hidden by calling show and hide IME consecutively with
* {@link android.view.inputmethod.InputMethodManager} APIs in
* {@link android.app.Activity#onCreate}.
*
* <p> Note for developers: Use {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_UNCHANGED}
* window flag to avoid some softInputMode visibility flags may take presence over
* {@link android.view.inputmethod.InputMethodManager} APIs (e.g. use showSoftInput to show
* IME in {@link android.app.Activity#onCreate} but being hidden by
* {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_ALWAYS_HIDDEN} window flag after the
* activity window focused).</p>
*/
@Test
public void testShowHideWithInputMethodManager_onCreate() {
if (mSoftInputFlags != SOFT_INPUT_STATE_UNCHANGED) {
return;
}
// Show and hide with InputMethodManager at onCreate()
Intent intent =
createIntent(
@@ -222,10 +239,7 @@ public final class ImeOpenCloseStressTest {
INPUT_METHOD_MANAGER_HIDE_ON_CREATE));
TestActivity activity = TestActivity.start(intent);
// TODO: The Ime is expected to show first and then hide. But show or hide
// with InputMethodManager at onCreate() would always fail because the window
// has not gained focus, so the actual behavior will be the same as auto-show.
// verifyHideBehavior(activity);
verifyHideBehavior(activity);
}
@Test
@@ -352,8 +366,7 @@ public final class ImeOpenCloseStressTest {
// Wait until IMMS / IMS handles messages.
SystemClock.sleep(1000);
mInstrumentation.waitForIdleSync();
// TODO(b/248456059): Ime should be hidden but is shown.
// verifyHideBehavior(activity);
verifyHideBehavior(activity);
mInstrumentation.runOnMainSync(activity::showImeWithWindowInsetsController);
verifyShowBehavior(activity);
@@ -420,11 +433,25 @@ public final class ImeOpenCloseStressTest {
verifyShowBehaviorNotRequestFocus(activity);
}
/**
* Test IME hidden by calling show and hide IME consecutively with
* {@link android.view.WindowInsetsController} APIs in {@link android.app.Activity#onCreate}.
*
* <p> Note for developers: Use {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_UNCHANGED}
* window flag to avoid some softInputMode visibility flags may take presence over
* {@link android.view.WindowInsetsController} APIs (e.g. use showSoftInput to show
* IME in {@link android.app.Activity#onCreate} but being hidden by
* {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_ALWAYS_HIDDEN} window flag after the
* activity window focused).</p>
*/
@Test
public void testHideWithWindowInsetsController_onCreate_requestFocus() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return;
}
if (mSoftInputFlags != SOFT_INPUT_STATE_UNCHANGED) {
return;
}
// Show and hide with InputMethodManager at onCreate()
Intent intent =
createIntent(
@@ -436,8 +463,7 @@ public final class ImeOpenCloseStressTest {
WINDOW_INSETS_CONTROLLER_HIDE_ON_CREATE));
TestActivity activity = TestActivity.start(intent);
// TODO(b/248456059): Ime should be hidden but is shown.
//verifyHideBehavior(activity);
verifyHideBehavior(activity);
}
@Test