summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java113
-rw-r--r--tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java40
2 files changed, 138 insertions, 15 deletions
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
index c84c2bcf19c6..92ea029bf469 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/AutoShowTest.java
@@ -18,9 +18,8 @@ package com.android.inputmethod.stresstest;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
+import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeIsAlwaysHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntil;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsShown;
@@ -30,19 +29,27 @@ import android.content.Intent;
import android.os.Bundle;
import android.platform.test.annotations.RootPermissionTest;
import android.platform.test.rule.UnlockScreenRule;
+import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests to verify the "auto show" behavior in {@code InputMethodManagerService} when the window
+ * gaining the focus to start the input.
+ */
@RootPermissionTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public final class AutoShowTest {
@Rule
@@ -52,18 +59,95 @@ public final class AutoShowTest {
public ScreenCaptureRule mScreenCaptureRule =
new ScreenCaptureRule("/sdcard/InputMethodStressTest");
+ private static final int[] SOFT_INPUT_VISIBILITY_FLAGS =
+ new int[] {
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED,
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN,
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN,
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE,
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE,
+ };
+
+ private static final int[] SOFT_INPUT_ADJUST_FLAGS =
+ new int[] {
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED,
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE,
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN,
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
+ };
+
+ // TODO(b/240359838): add test case {@code Configuration.SCREENLAYOUT_SIZE_LARGE}.
+ @Parameterized.Parameters(
+ name =
+ "softInputVisibility={0}, softInputAdjustment={1},"
+ + " softInputModeIsForwardNavigation={2}")
+ public static List<Object[]> softInputModeConfigs() {
+ ArrayList<Object[]> params = new ArrayList<>();
+ for (int softInputVisibility : SOFT_INPUT_VISIBILITY_FLAGS) {
+ for (int softInputAdjust : SOFT_INPUT_ADJUST_FLAGS) {
+ params.add(new Object[] {softInputVisibility, softInputAdjust, true});
+ params.add(new Object[] {softInputVisibility, softInputAdjust, false});
+ }
+ }
+ return params;
+ }
+
+ private static final String SOFT_INPUT_FLAGS = "soft_input_flags";
+
+ private final int mSoftInputVisibility;
+ private final int mSoftInputAdjustment;
+ private final boolean mSoftInputIsForwardNavigation;
+
+ public AutoShowTest(
+ int softInputVisibility,
+ int softInputAdjustment,
+ boolean softInputIsForwardNavigation) {
+ mSoftInputVisibility = softInputVisibility;
+ mSoftInputAdjustment = softInputAdjustment;
+ mSoftInputIsForwardNavigation = softInputIsForwardNavigation;
+ }
+
@Test
public void autoShow() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- Intent intent = new Intent()
- .setAction(Intent.ACTION_MAIN)
- .setClass(instrumentation.getContext(), TestActivity.class)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ int flags = mSoftInputVisibility | mSoftInputAdjustment;
+ if (mSoftInputIsForwardNavigation) {
+ flags |= WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
+ }
+
+ Intent intent =
+ new Intent()
+ .setAction(Intent.ACTION_MAIN)
+ .setClass(instrumentation.getContext(), TestActivity.class)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .putExtra(SOFT_INPUT_FLAGS, flags);
TestActivity activity = (TestActivity) instrumentation.startActivitySync(intent);
EditText editText = activity.getEditText();
waitOnMainUntil("activity should gain focus", editText::hasWindowFocus);
- waitOnMainUntilImeIsShown(editText);
+
+ if (mSoftInputVisibility == WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
+ || mSoftInputVisibility
+ == WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) {
+ // IME will be auto-shown if softInputMode is set with flag:
+ // SOFT_INPUT_STATE_VISIBLE or SOFT_INPUT_STATE_ALWAYS_VISIBLE
+ waitOnMainUntilImeIsShown(editText);
+ } else if (mSoftInputVisibility == WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
+ || mSoftInputVisibility
+ == WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) {
+ // IME will be not be shown if softInputMode is set with flag:
+ // SOFT_INPUT_STATE_HIDDEN or SOFT_INPUT_STATE_ALWAYS_HIDDEN
+ verifyImeIsAlwaysHidden(editText);
+ } else {
+ // The current system behavior will choose to show IME automatically when navigating
+ // forward to an app that has no visibility state specified (i.e.
+ // SOFT_INPUT_STATE_UNSPECIFIED) with set SOFT_INPUT_ADJUST_RESIZE flag.
+ if (mSoftInputVisibility == WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
+ && mSoftInputAdjustment == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
+ && mSoftInputIsForwardNavigation) {
+ waitOnMainUntilImeIsShown(editText);
+ }
+ }
}
public static class TestActivity extends Activity {
@@ -72,16 +156,15 @@ public final class AutoShowTest {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // IME will be auto-shown if the following conditions are met:
- // 1. SoftInputMode state is SOFT_INPUT_STATE_UNSPECIFIED.
- // 2. SoftInputMode adjust is SOFT_INPUT_ADJUST_RESIZE.
- getWindow().setSoftInputMode(SOFT_INPUT_STATE_UNSPECIFIED | SOFT_INPUT_ADJUST_RESIZE);
+ int flags = getIntent().getIntExtra(SOFT_INPUT_FLAGS, 0);
+ getWindow().setSoftInputMode(flags);
LinearLayout rootView = new LinearLayout(this);
rootView.setOrientation(LinearLayout.VERTICAL);
mEditText = new EditText(this);
rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
setContentView(rootView);
- // 3. The focused view is a text editor (View#onCheckIsTextEditor() returns true).
+ // Ensure the focused view is a text editor (View#onCheckIsTextEditor() returns true) to
+ // automatically display a soft input window.
mEditText.requestFocus();
}
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
index ba2ba3c75bc2..b6d462c6203d 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/ImeStressTestUtil.java
@@ -25,6 +25,8 @@ import android.view.WindowInsets;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.ThrowingRunnable;
+
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@@ -33,6 +35,7 @@ import java.util.concurrent.atomic.AtomicReference;
public final class ImeStressTestUtil {
private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+ private static final long VERIFY_DURATION = TimeUnit.SECONDS.toMillis(2);
private ImeStressTestUtil() {
}
@@ -77,4 +80,41 @@ public final class ImeStressTestUtil {
eventually(() -> assertWithMessage("IME should be hidden").that(
callOnMainSync(() -> isImeShown(view))).isFalse(), TIMEOUT);
}
+
+ /** Verify IME is always hidden within the given time duration. */
+ public static void verifyImeIsAlwaysHidden(View view) {
+ always(
+ () ->
+ assertWithMessage("IME should be hidden")
+ .that(callOnMainSync(() -> isImeShown(view)))
+ .isFalse(),
+ VERIFY_DURATION);
+ }
+
+ /**
+ * Make sure that a {@link Runnable} always finishes without throwing a {@link Exception} in the
+ * given duration
+ *
+ * @param r The {@link Runnable} to run.
+ * @param timeoutMillis The number of milliseconds to wait for {@code r} to not throw
+ */
+ public static void always(ThrowingRunnable r, long timeoutMillis) {
+ long start = System.currentTimeMillis();
+
+ while (true) {
+ try {
+ r.run();
+ if (System.currentTimeMillis() - start >= timeoutMillis) {
+ return;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ignored) {
+ // Do nothing
+ }
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
}