Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c875788c authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Improve InputMethodStressTest annotations

Extract methods for requesting IME focus on the view, on the main thread,
and asserting the request is successful.

Update assertion messages to be more explicit about the expected
outcome, and the value being asserted on.

Bug: 292086579
Test: atest InputMethodStressTest
Change-Id: I40fce41cb890349877cf1384d883599d15093378
parent 5d425594
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.inputmethod.stresstest.ImeStressTestUtil.UNFOCUSABLE_V
import static com.android.inputmethod.stresstest.ImeStressTestUtil.callOnMainSync;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.callOnMainSync;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.getWindowAndSoftInputFlagParameters;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.getWindowAndSoftInputFlagParameters;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.hasUnfocusableWindowFlags;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.hasUnfocusableWindowFlags;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.requestFocusAndVerify;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeAlwaysHiddenWithWindowFlagSet;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeAlwaysHiddenWithWindowFlagSet;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeIsAlwaysHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeIsAlwaysHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
@@ -225,7 +226,7 @@ public final class AutoShowTest {
        Intent intent1 = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent1 = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity firstActivity = TestActivity.start(intent1);
        TestActivity firstActivity = TestActivity.start(intent1);
        // Request view focus after app starts
        // Request view focus after app starts
        mInstrumentation.runOnMainSync(firstActivity::requestFocus);
        requestFocusAndVerify(firstActivity);


        Intent intent2 =
        Intent intent2 =
                createIntent(
                createIntent(
@@ -252,7 +253,7 @@ public final class AutoShowTest {
        Intent intent1 = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent1 = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent1);
        TestActivity activity = TestActivity.start(intent1);
        // Request view focus after app starts
        // Request view focus after app starts
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        // Create second TestActivity
        // Create second TestActivity
        Intent intent2 =
        Intent intent2 =
@@ -284,7 +285,7 @@ public final class AutoShowTest {
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request view focus after app starts
        // Request view focus after app starts
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        // Find the editText and click it
        // Find the editText and click it
        UiObject2 editTextUiObject =
        UiObject2 editTextUiObject =
+3 −2
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.REQUEST_FOCUS_ON_CREATE;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.REQUEST_FOCUS_ON_CREATE;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.TestActivity.createIntent;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.TestActivity.createIntent;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.callOnMainSync;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.callOnMainSync;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.requestFocusAndVerify;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsShown;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUntilImeIsShown;
@@ -96,7 +97,7 @@ public final class DefaultImeVisibilityTest {
        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        eventually(
        eventually(
                () ->
                () ->
                        assertWithMessage("Display rotation should be updated.")
                        assertWithMessage("Display rotation should have been updated")
                                .that(uiDevice.getDisplayRotation())
                                .that(uiDevice.getDisplayRotation())
                                .isEqualTo(mIsPortrait ? 0 : 1),
                                .isEqualTo(mIsPortrait ? 0 : 1),
                TIMEOUT);
                TIMEOUT);
@@ -104,7 +105,7 @@ public final class DefaultImeVisibilityTest {
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
            // TODO(b/291752364): Remove the explicit focus request once the issue with view focus
            // TODO(b/291752364): Remove the explicit focus request once the issue with view focus
            //  change between fullscreen IME and actual editText is fixed.
            //  change between fullscreen IME and actual editText is fixed.
            callOnMainSync(editText::requestFocus);
            requestFocusAndVerify(activity);
            verifyWindowAndViewFocus(editText, true, true);
            verifyWindowAndViewFocus(editText, true, true);
            callOnMainSync(activity::showImeWithInputMethodManager);
            callOnMainSync(activity::showImeWithInputMethodManager);
            waitOnMainUntilImeIsShown(editText);
            waitOnMainUntilImeIsShown(editText);
+40 −59
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import static com.android.inputmethod.stresstest.ImeStressTestUtil.callOnMainSyn
import static com.android.inputmethod.stresstest.ImeStressTestUtil.getWindowAndSoftInputFlagParameters;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.getWindowAndSoftInputFlagParameters;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.hasUnfocusableWindowFlags;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.hasUnfocusableWindowFlags;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.isImeShown;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.isImeShown;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.requestFocusAndVerify;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeAlwaysHiddenWithWindowFlagSet;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeAlwaysHiddenWithWindowFlagSet;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeIsAlwaysHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyImeIsAlwaysHidden;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
import static com.android.inputmethod.stresstest.ImeStressTestUtil.verifyWindowAndViewFocus;
@@ -38,6 +39,9 @@ import static com.android.inputmethod.stresstest.ImeStressTestUtil.waitOnMainUnt


import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;


import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import android.app.Instrumentation;
import android.app.Instrumentation;
import android.content.Intent;
import android.content.Intent;
import android.os.Build;
import android.os.Build;
@@ -96,7 +100,8 @@ public final class ImeOpenCloseStressTest {
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);

        // Test only once if window flags set to save time.
        // Test only once if window flags set to save time.
        int iterNum = hasUnfocusableWindowFlags(activity) ? 1 : NUM_TEST_ITERATIONS;
        int iterNum = hasUnfocusableWindowFlags(activity) ? 1 : NUM_TEST_ITERATIONS;
        for (int i = 0; i < iterNum; i++) {
        for (int i = 0; i < iterNum; i++) {
@@ -106,21 +111,19 @@ public final class ImeOpenCloseStressTest {
            verifyShowBehavior(activity);
            verifyShowBehavior(activity);


            callOnMainSync(activity::hideImeWithInputMethodManager);
            callOnMainSync(activity::hideImeWithInputMethodManager);

            verifyHideBehavior(activity);
            verifyHideBehavior(activity);
        }
        }
    }
    }


    @Test
    @Test
    public void testShowHideWithInputMethodManager_waitingAnimationEnd() {
    public void testShowHideWithInputMethodManager_waitingAnimationEnd() {
        assumeFalse("Has unfocusable window flags", hasUnfocusableWindowFlags(mWindowFocusFlags));

        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        if (hasUnfocusableWindowFlags(activity)) {
            return; // Skip to save time.
        }
        activity.enableAnimationMonitoring();
        activity.enableAnimationMonitoring();
        EditText editText = activity.getEditText();
        EditText editText = activity.getEditText();
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
@@ -128,12 +131,12 @@ public final class ImeOpenCloseStressTest {
            Log.i(TAG, msgPrefix + "start");
            Log.i(TAG, msgPrefix + "start");
            callOnMainSync(activity::showImeWithInputMethodManager);
            callOnMainSync(activity::showImeWithInputMethodManager);
            waitOnMainUntil(
            waitOnMainUntil(
                    msgPrefix + "IME should be visible",
                    msgPrefix + "IME should have been shown",
                    () -> !activity.isAnimating() && isImeShown(editText));
                    () -> !activity.isAnimating() && isImeShown(editText));


            callOnMainSync(activity::hideImeWithInputMethodManager);
            callOnMainSync(activity::hideImeWithInputMethodManager);
            waitOnMainUntil(
            waitOnMainUntil(
                    msgPrefix + "IME should be hidden",
                    msgPrefix + "IME should have been hidden",
                    () -> !activity.isAnimating() && !isImeShown(editText));
                    () -> !activity.isAnimating() && !isImeShown(editText));
        }
        }
    }
    }
@@ -141,13 +144,13 @@ public final class ImeOpenCloseStressTest {
    @Test
    @Test
    public void testShowHideWithInputMethodManager_intervalAfterHide() {
    public void testShowHideWithInputMethodManager_intervalAfterHide() {
        // Regression test for b/221483132
        // Regression test for b/221483132
        assumeFalse("Has unfocusable window flags", hasUnfocusableWindowFlags(mWindowFocusFlags));

        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);
        if (hasUnfocusableWindowFlags(activity)) {

            return; // Skip to save time.
        }
        // Intervals = 10, 20, 30, ..., 100, 150, 200, ...
        // Intervals = 10, 20, 30, ..., 100, 150, 200, ...
        List<Integer> intervals = new ArrayList<>();
        List<Integer> intervals = new ArrayList<>();
        for (int i = 10; i < 100; i += 10) intervals.add(i);
        for (int i = 10; i < 100; i += 10) intervals.add(i);
@@ -165,14 +168,12 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowHideWithInputMethodManager_inSameFrame() {
    public void testShowHideWithInputMethodManager_inSameFrame() {
        assumeFalse("Has unfocusable window flags", hasUnfocusableWindowFlags(mWindowFocusFlags));
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        if (hasUnfocusableWindowFlags(activity)) {
            return; // Skip to save time.
        }
        // hidden -> show -> hide
        // hidden -> show -> hide
        mInstrumentation.runOnMainSync(
        mInstrumentation.runOnMainSync(
                () -> {
                () -> {
@@ -256,13 +257,12 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowHideWithWindowInsetsController_waitingVisibilityChange() {
    public void testShowHideWithWindowInsetsController_waitingVisibilityChange() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        }
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);

        // Test only once if window flags set to save time.
        // Test only once if window flags set to save time.
        int iterNum = hasUnfocusableWindowFlags(activity) ? 1 : NUM_TEST_ITERATIONS;
        int iterNum = hasUnfocusableWindowFlags(activity) ? 1 : NUM_TEST_ITERATIONS;
        for (int i = 0; i < iterNum; i++) {
        for (int i = 0; i < iterNum; i++) {
@@ -277,17 +277,13 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowHideWithWindowInsetsController_waitingAnimationEnd() {
    public void testShowHideWithWindowInsetsController_waitingAnimationEnd() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        assumeFalse("Has unfocusable window flags", hasUnfocusableWindowFlags(mWindowFocusFlags));
        }
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        if (hasUnfocusableWindowFlags(activity)) {
            return; // Skip to save time.
        }
        activity.enableAnimationMonitoring();
        activity.enableAnimationMonitoring();
        EditText editText = activity.getEditText();
        EditText editText = activity.getEditText();
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
        for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
@@ -295,29 +291,25 @@ public final class ImeOpenCloseStressTest {
            Log.i(TAG, msgPrefix + "start");
            Log.i(TAG, msgPrefix + "start");
            mInstrumentation.runOnMainSync(activity::showImeWithWindowInsetsController);
            mInstrumentation.runOnMainSync(activity::showImeWithWindowInsetsController);
            waitOnMainUntil(
            waitOnMainUntil(
                    msgPrefix + "IME should be visible",
                    msgPrefix + "IME should have been shown",
                    () -> !activity.isAnimating() && isImeShown(editText));
                    () -> !activity.isAnimating() && isImeShown(editText));


            mInstrumentation.runOnMainSync(activity::hideImeWithWindowInsetsController);
            mInstrumentation.runOnMainSync(activity::hideImeWithWindowInsetsController);
            waitOnMainUntil(
            waitOnMainUntil(
                    msgPrefix + "IME should be hidden",
                    msgPrefix + "IME should have been hidden",
                    () -> !activity.isAnimating() && !isImeShown(editText));
                    () -> !activity.isAnimating() && !isImeShown(editText));
        }
        }
    }
    }


    @Test
    @Test
    public void testShowHideWithWindowInsetsController_intervalAfterHide() {
    public void testShowHideWithWindowInsetsController_intervalAfterHide() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        assumeFalse("Has unfocusable window flags", hasUnfocusableWindowFlags(mWindowFocusFlags));
        }
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        if (hasUnfocusableWindowFlags(activity)) {
            return; // Skip to save time.
        }
        // Intervals = 10, 20, 30, ..., 100, 150, 200, ...
        // Intervals = 10, 20, 30, ..., 100, 150, 200, ...
        List<Integer> intervals = new ArrayList<>();
        List<Integer> intervals = new ArrayList<>();
        for (int i = 10; i < 100; i += 10) intervals.add(i);
        for (int i = 10; i < 100; i += 10) intervals.add(i);
@@ -335,17 +327,13 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowHideWithWindowInsetsController_inSameFrame() {
    public void testShowHideWithWindowInsetsController_inSameFrame() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        assumeFalse("Has unfocusable window flags", hasUnfocusableWindowFlags(mWindowFocusFlags));
        }
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        // Request focus after app starts to avoid triggering auto-show behavior.
        // Request focus after app starts to avoid triggering auto-show behavior.
        mInstrumentation.runOnMainSync(activity::requestFocus);
        requestFocusAndVerify(activity);


        if (hasUnfocusableWindowFlags(activity)) {
            return; // Skip to save time.
        }
        // hidden -> show -> hide
        // hidden -> show -> hide
        mInstrumentation.runOnMainSync(
        mInstrumentation.runOnMainSync(
                () -> {
                () -> {
@@ -377,9 +365,7 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowWithWindowInsetsController_onCreate_requestFocus() {
    public void testShowWithWindowInsetsController_onCreate_requestFocus() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        }
        // Show with InputMethodManager at onCreate()
        // Show with InputMethodManager at onCreate()
        Intent intent =
        Intent intent =
                createIntent(
                createIntent(
@@ -394,10 +380,8 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowWithWindowInsetsController_onCreate_notRequestFocus() {
    public void testShowWithWindowInsetsController_onCreate_notRequestFocus() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        // Show and hide with WindowInsetsController at onCreate()
        }
        // Show and hide with InputMethodManager at onCreate()
        Intent intent =
        Intent intent =
                createIntent(
                createIntent(
                        mWindowFocusFlags,
                        mWindowFocusFlags,
@@ -411,10 +395,8 @@ public final class ImeOpenCloseStressTest {


    @Test
    @Test
    public void testShowWithWindowInsetsController_afterStart_notRequestFocus() {
    public void testShowWithWindowInsetsController_afterStart_notRequestFocus() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        // Show and hide with WindowInsetsController at onCreate()
        }
        // Show and hide with InputMethodManager at onCreate()
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        Intent intent = createIntent(mWindowFocusFlags, mSoftInputFlags, Collections.emptyList());
        TestActivity activity = TestActivity.start(intent);
        TestActivity activity = TestActivity.start(intent);
        mInstrumentation.runOnMainSync(activity::showImeWithWindowInsetsController);
        mInstrumentation.runOnMainSync(activity::showImeWithWindowInsetsController);
@@ -425,7 +407,8 @@ public final class ImeOpenCloseStressTest {


    /**
    /**
     * Test IME hidden by calling show and hide IME consecutively with
     * Test IME hidden by calling show and hide IME consecutively with
     * {@link android.view.WindowInsetsController} APIs in {@link android.app.Activity#onCreate}.
     * {@link android.view.WindowInsetsController} APIs in
     * {@link android.app.Activity#onCreate}.
     *
     *
     * <p> Note for developers: Use {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_UNCHANGED}
     * <p> Note for developers: Use {@link WindowManager.LayoutParams#SOFT_INPUT_STATE_UNCHANGED}
     * window flag to avoid some softInputMode visibility flags may take presence over
     * window flag to avoid some softInputMode visibility flags may take presence over
@@ -436,13 +419,11 @@ public final class ImeOpenCloseStressTest {
     */
     */
    @Test
    @Test
    public void testHideWithWindowInsetsController_onCreate_requestFocus() {
    public void testHideWithWindowInsetsController_onCreate_requestFocus() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
        assumeTrue("Is at least Android R", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
            return;
        }
        if (mSoftInputFlags != SOFT_INPUT_STATE_UNCHANGED) {
        if (mSoftInputFlags != SOFT_INPUT_STATE_UNCHANGED) {
            return;
            return;
        }
        }
        // Show and hide with InputMethodManager at onCreate()
        // Show and hide with WindowInsetsController at onCreate()
        Intent intent =
        Intent intent =
                createIntent(
                createIntent(
                        mWindowFocusFlags,
                        mWindowFocusFlags,
+52 −21
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.LinearLayout;


import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.platform.app.InstrumentationRegistry;


@@ -148,6 +149,14 @@ public final class ImeStressTestUtil {
        return result.get();
        return result.get();
    }
    }


    /**
     * Requests EditText view focus on the main thread, and assert this returns {@code true}.
     */
    public static void requestFocusAndVerify(TestActivity activity) {
        boolean result = callOnMainSync(activity::requestFocus);
        assertWithMessage("View focus request should have succeeded").that(result).isTrue();
    }

    /**
    /**
     * Waits until {@code pred} returns true, or throws on timeout.
     * Waits until {@code pred} returns true, or throws on timeout.
     *
     *
@@ -161,7 +170,7 @@ public final class ImeStressTestUtil {
    public static void waitOnMainUntilImeIsShown(View view) {
    public static void waitOnMainUntilImeIsShown(View view) {
        eventually(
        eventually(
                () ->
                () ->
                        assertWithMessage("IME should be shown")
                        assertWithMessage("IME should have been shown")
                                .that(callOnMainSync(() -> isImeShown(view)))
                                .that(callOnMainSync(() -> isImeShown(view)))
                                .isTrue(),
                                .isTrue(),
                TIMEOUT);
                TIMEOUT);
@@ -171,27 +180,28 @@ public final class ImeStressTestUtil {
    public static void waitOnMainUntilImeIsHidden(View view) {
    public static void waitOnMainUntilImeIsHidden(View view) {
        eventually(
        eventually(
                () ->
                () ->
                        assertWithMessage("IME should be hidden")
                        assertWithMessage("IME should have been hidden")
                                .that(callOnMainSync(() -> isImeShown(view)))
                                .that(callOnMainSync(() -> isImeShown(view)))
                                .isFalse(),
                                .isFalse(),
                TIMEOUT);
                TIMEOUT);
    }
    }


    /** Waits until window get focus, or throws on timeout. */
    /** Waits until window gains focus, or throws on timeout. */
    public static void waitOnMainUntilWindowGainsFocus(View view) {
    public static void waitOnMainUntilWindowGainsFocus(View view) {
        eventually(
        eventually(
                () ->
                () ->
                        assertWithMessage("Window should gain focus")
                        assertWithMessage(
                                "Window should have gained focus; value of hasWindowFocus:")
                                .that(callOnMainSync(view::hasWindowFocus))
                                .that(callOnMainSync(view::hasWindowFocus))
                                .isTrue(),
                                .isTrue(),
                TIMEOUT);
                TIMEOUT);
    }
    }


    /** Waits until view get focus, or throws on timeout. */
    /** Waits until view gains focus, or throws on timeout. */
    public static void waitOnMainUntilViewGainsFocus(View view) {
    public static void waitOnMainUntilViewGainsFocus(View view) {
        eventually(
        eventually(
                () ->
                () ->
                        assertWithMessage("View should gain focus")
                        assertWithMessage("View should have gained focus; value of hasFocus:")
                                .that(callOnMainSync(view::hasFocus))
                                .that(callOnMainSync(view::hasFocus))
                                .isTrue(),
                                .isTrue(),
                TIMEOUT);
                TIMEOUT);
@@ -201,7 +211,7 @@ public final class ImeStressTestUtil {
    public static void verifyImeIsAlwaysHidden(View view) {
    public static void verifyImeIsAlwaysHidden(View view) {
        always(
        always(
                () ->
                () ->
                        assertWithMessage("IME should be hidden")
                        assertWithMessage("IME should have been hidden")
                                .that(callOnMainSync(() -> isImeShown(view)))
                                .that(callOnMainSync(() -> isImeShown(view)))
                                .isFalse(),
                                .isFalse(),
                TIMEOUT);
                TIMEOUT);
@@ -211,7 +221,8 @@ public final class ImeStressTestUtil {
    public static void verifyWindowNeverGainsFocus(View view) {
    public static void verifyWindowNeverGainsFocus(View view) {
        always(
        always(
                () ->
                () ->
                        assertWithMessage("window should never gain focus")
                        assertWithMessage(
                                "Window should not have gained focus; value of hasWindowFocus:")
                                .that(callOnMainSync(view::hasWindowFocus))
                                .that(callOnMainSync(view::hasWindowFocus))
                                .isFalse(),
                                .isFalse(),
                TIMEOUT);
                TIMEOUT);
@@ -221,7 +232,7 @@ public final class ImeStressTestUtil {
    public static void verifyViewNeverGainsFocus(View view) {
    public static void verifyViewNeverGainsFocus(View view) {
        always(
        always(
                () ->
                () ->
                        assertWithMessage("view should never gain ime focus")
                        assertWithMessage("View should not have gained focus; value of hasFocus:")
                                .that(callOnMainSync(view::hasFocus))
                                .that(callOnMainSync(view::hasFocus))
                                .isFalse(),
                                .isFalse(),
                TIMEOUT);
                TIMEOUT);
@@ -254,8 +265,23 @@ public final class ImeStressTestUtil {
        }
        }
    }
    }


    /**
     * Returns {@code true} if the activity can't receive IME focus, based on its window flags,
     * and {@code false} otherwise.
     *
     * @param activity the activity to check.
     */
    public static boolean hasUnfocusableWindowFlags(Activity activity) {
    public static boolean hasUnfocusableWindowFlags(Activity activity) {
        int windowFlags = activity.getWindow().getAttributes().flags;
        return hasUnfocusableWindowFlags(activity.getWindow().getAttributes().flags);
    }

    /**
     * Returns {@code true} if the activity can't receive IME focus, based on its window flags,
     * and {@code false} otherwise.
     *
     * @param windowFlags the window flags to check.
     */
    public static boolean hasUnfocusableWindowFlags(int windowFlags) {
        return (windowFlags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0
        return (windowFlags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0
                || (windowFlags & LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0
                || (windowFlags & LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0
                || (windowFlags & LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
                || (windowFlags & LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
@@ -302,22 +328,26 @@ public final class ImeStressTestUtil {


        private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
        private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
                new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
                new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
                    @NonNull
                    @Override
                    @Override
                    public WindowInsetsAnimation.Bounds onStart(
                    public WindowInsetsAnimation.Bounds onStart(
                            WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) {
                            @NonNull WindowInsetsAnimation animation,
                            @NonNull WindowInsetsAnimation.Bounds bounds) {
                        mIsAnimating = true;
                        mIsAnimating = true;
                        return super.onStart(animation, bounds);
                        return super.onStart(animation, bounds);
                    }
                    }


                    @Override
                    @Override
                    public void onEnd(WindowInsetsAnimation animation) {
                    public void onEnd(@NonNull WindowInsetsAnimation animation) {
                        super.onEnd(animation);
                        super.onEnd(animation);
                        mIsAnimating = false;
                        mIsAnimating = false;
                    }
                    }


                    @NonNull
                    @Override
                    @Override
                    public WindowInsets onProgress(
                    public WindowInsets onProgress(
                            WindowInsets insets, List<WindowInsetsAnimation> runningAnimations) {
                            @NonNull WindowInsets insets,
                            @NonNull List<WindowInsetsAnimation> runningAnimations) {
                        return insets;
                        return insets;
                    }
                    }
                };
                };
@@ -394,7 +424,7 @@ public final class ImeStressTestUtil {
                    getInputMethodManager()
                    getInputMethodManager()
                            .showSoftInput(mEditText, 0 /* flags */);
                            .showSoftInput(mEditText, 0 /* flags */);
            if (showResult) {
            if (showResult) {
                Log.i(TAG, "IMM#showSoftInput successfully");
                Log.i(TAG, "IMM#showSoftInput succeeded");
            } else {
            } else {
                Log.i(TAG, "IMM#showSoftInput failed");
                Log.i(TAG, "IMM#showSoftInput failed");
            }
            }
@@ -407,7 +437,7 @@ public final class ImeStressTestUtil {
                    getInputMethodManager()
                    getInputMethodManager()
                            .hideSoftInputFromWindow(mEditText.getWindowToken(), 0 /* flags */);
                            .hideSoftInputFromWindow(mEditText.getWindowToken(), 0 /* flags */);
            if (hideResult) {
            if (hideResult) {
                Log.i(TAG, "IMM#hideSoftInput successfully");
                Log.i(TAG, "IMM#hideSoftInput succeeded");
            } else {
            } else {
                Log.i(TAG, "IMM#hideSoftInput failed");
                Log.i(TAG, "IMM#hideSoftInput failed");
            }
            }
@@ -421,7 +451,7 @@ public final class ImeStressTestUtil {
            }
            }
            Log.i(TAG, "showImeWithWIC()");
            Log.i(TAG, "showImeWithWIC()");
            WindowInsetsController windowInsetsController = mEditText.getWindowInsetsController();
            WindowInsetsController windowInsetsController = mEditText.getWindowInsetsController();
            assertWithMessage("WindowInsetsController shouldn't be null.")
            assertWithMessage("WindowInsetsController")
                    .that(windowInsetsController)
                    .that(windowInsetsController)
                    .isNotNull();
                    .isNotNull();
            windowInsetsController.show(WindowInsets.Type.ime());
            windowInsetsController.show(WindowInsets.Type.ime());
@@ -434,7 +464,7 @@ public final class ImeStressTestUtil {
            }
            }
            Log.i(TAG, "hideImeWithWIC()");
            Log.i(TAG, "hideImeWithWIC()");
            WindowInsetsController windowInsetsController = mEditText.getWindowInsetsController();
            WindowInsetsController windowInsetsController = mEditText.getWindowInsetsController();
            assertWithMessage("WindowInsetsController shouldn't be null.")
            assertWithMessage("WindowInsetsController")
                    .that(windowInsetsController)
                    .that(windowInsetsController)
                    .isNotNull();
                    .isNotNull();
            windowInsetsController.hide(WindowInsets.Type.ime());
            windowInsetsController.hide(WindowInsets.Type.ime());
@@ -482,13 +512,14 @@ public final class ImeStressTestUtil {
            return mIsAnimating;
            return mIsAnimating;
        }
        }


        public void requestFocus() {
        public boolean requestFocus() {
            boolean requestFocusResult = getEditText().requestFocus();
            boolean requestFocusResult = mEditText.requestFocus();
            if (requestFocusResult) {
            if (requestFocusResult) {
                Log.i(TAG, "Request focus successfully");
                Log.i(TAG, "View#requestFocus succeeded");
            } else {
            } else {
                Log.i(TAG, "Request focus failed");
                Log.i(TAG, "View#requestFocus failed");
            }
            }
            return requestFocusResult;
        }
        }
    }
    }
}
}