summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Cosmin Băieș <cosminbaies@google.com> 2025-02-04 18:48:18 +0100
committer Cosmin Băieș <cosminbaies@google.com> 2025-02-05 16:32:43 +0100
commiteeccf514a5de1ddf9ecff587f23750116b5871ee (patch)
tree77c07262f849cb3afe2f3ea41d0ff6ae62100999
parent8c3f859c6d4f9e186b725265965a8cd56ac5e4cb (diff)
Cleanup InputMethodServiceTest and SimpleIMS
This cleans up the InputMethodServiceTest code, as well as SimpleIMS and its TestActivity, by clarifying method/field names, adding nullability annotations, and introducing assertion messages. Additionally removed the return value from showing/hiding the IME via the InsetsController APIs, as these were always returning true. Extracted separate methods for checking whether there is a navigation bar, and setting the IME NavButtonFlags manually. Ensured the countDownLatchForTesting is reset after usage. Explicilty handled exceptions by failing the test with a clear message. Added the missing testShowHideKeyboard_byInputMethodManager test. Removed an incorrect assertion from testImeSwitchButtonLongClick. Flag: EXEMPT testfix Bug: 394328311 Test: atest InputMethodServiceTest Change-Id: Id4aaa987114d4a90213f20a2e0895776b4eab0a5
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java655
-rw-r--r--services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleInputMethodService.java27
-rw-r--r--services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleKeyboard.java106
-rw-r--r--services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/ims/InputMethodServiceWrapper.java41
-rw-r--r--services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java53
5 files changed, 490 insertions, 392 deletions
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index c954b185914c..27adec003355 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -19,11 +19,12 @@ package com.android.inputmethodservice;
import static android.view.WindowInsets.Type.captionBar;
import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.internal.inputmethod.InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR;
+import static com.android.internal.inputmethod.InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@@ -49,6 +50,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
@@ -56,7 +58,6 @@ import androidx.test.uiautomator.Until;
import com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper;
import com.android.apps.inputmethod.simpleime.testing.TestActivity;
import com.android.compatibility.common.util.SystemUtil;
-import com.android.internal.inputmethod.InputMethodNavButtonFlags;
import org.junit.After;
import org.junit.Before;
@@ -64,7 +65,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -72,6 +72,7 @@ import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class InputMethodServiceTest {
+
private static final String TAG = "SimpleIMSTest";
private static final String INPUT_METHOD_SERVICE_NAME = ".SimpleInputMethodService";
private static final String EDIT_TEXT_DESC = "Input box";
@@ -87,45 +88,50 @@ public class InputMethodServiceTest {
private final DeviceFlagsValueProvider mFlagsValueProvider = new DeviceFlagsValueProvider();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = new CheckFlagsRule(mFlagsValueProvider);
+
private Instrumentation mInstrumentation;
private UiDevice mUiDevice;
private Context mContext;
+ private InputMethodManager mImm;
private String mTargetPackageName;
+ private String mInputMethodId;
private TestActivity mActivity;
private InputMethodServiceWrapper mInputMethodService;
- private String mInputMethodId;
private boolean mShowImeWithHardKeyboardEnabled;
- @Rule
- public final CheckFlagsRule mCheckFlagsRule = new CheckFlagsRule(mFlagsValueProvider);
-
@Before
public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mUiDevice = UiDevice.getInstance(mInstrumentation);
mContext = mInstrumentation.getContext();
+ mImm = mContext.getSystemService(InputMethodManager.class);
mTargetPackageName = mInstrumentation.getTargetContext().getPackageName();
mInputMethodId = getInputMethodId();
prepareIme();
- prepareEditor();
+ prepareActivity();
mInstrumentation.waitForIdleSync();
mUiDevice.freezeRotation();
mUiDevice.setOrientationNatural();
// Waits for input binding ready.
eventually(() -> {
- mInputMethodService =
- InputMethodServiceWrapper.getInputMethodServiceWrapperForTesting();
- assertThat(mInputMethodService).isNotNull();
+ mInputMethodService = InputMethodServiceWrapper.getInstance();
+ assertWithMessage("IME is not null").that(mInputMethodService).isNotNull();
// The activity gets focus.
- assertThat(mActivity.hasWindowFocus()).isTrue();
- assertThat(mInputMethodService.getCurrentInputEditorInfo()).isNotNull();
- assertThat(mInputMethodService.getCurrentInputEditorInfo().packageName)
- .isEqualTo(mTargetPackageName);
-
- // The editor won't bring up keyboard by default.
- assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
- assertThat(mInputMethodService.getCurrentInputViewStarted()).isFalse();
+ assertWithMessage("Activity window has input focus")
+ .that(mActivity.hasWindowFocus()).isTrue();
+ final var editorInfo = mInputMethodService.getCurrentInputEditorInfo();
+ assertWithMessage("EditorInfo is not null").that(editorInfo).isNotNull();
+ assertWithMessage("EditorInfo package matches target package")
+ .that(editorInfo.packageName).isEqualTo(mTargetPackageName);
+
+ assertWithMessage("Input connection is started")
+ .that(mInputMethodService.getCurrentInputStarted()).isTrue();
+ // The editor won't bring up the IME by default.
+ assertWithMessage("IME is not shown during setup")
+ .that(mInputMethodService.getCurrentInputViewStarted()).isFalse();
});
// Save the original value of show_ime_with_hard_keyboard from Settings.
mShowImeWithHardKeyboardEnabled = Settings.Secure.getInt(
@@ -148,30 +154,63 @@ public class InputMethodServiceTest {
* (i.e. tapping on an EditText, tapping the Home button).
*/
@Test
- public void testShowHideKeyboard_byUserAction() throws Exception {
+ public void testShowHideKeyboard_byUserAction() {
setShowImeWithHardKeyboard(true /* enabled */);
- // Performs click on editor box to bring up the soft keyboard.
- Log.i(TAG, "Click on EditText.");
+ // Performs click on EditText to bring up the IME.
+ Log.i(TAG, "Click on EditText");
verifyInputViewStatus(
- () -> clickOnEditorText(),
+ this::clickOnEditText,
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- // Press home key to hide soft keyboard.
+ // Press home key to hide IME.
Log.i(TAG, "Press home");
if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
- assertThat(mUiDevice.pressHome()).isTrue();
+ assertWithMessage("Home key press was handled").that(mUiDevice.pressHome()).isTrue();
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
} else {
verifyInputViewStatus(
- () -> assertThat(mUiDevice.pressHome()).isTrue(),
+ () -> assertWithMessage("Home key press was handled")
+ .that(mUiDevice.pressHome()).isTrue(),
true /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
+ }
+ }
+
+ /**
+ * This checks that the IME can be shown and hidden using the InputMethodManager APIs.
+ */
+ @Test
+ public void testShowHideKeyboard_byInputMethodManager() {
+ setShowImeWithHardKeyboard(true /* enabled */);
+
+ // Triggers to show IME via public API.
+ verifyInputViewStatusOnMainSync(
+ () -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
+ true /* expected */,
+ true /* inputViewStarted */);
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
+
+ // Triggers to hide IME via public API.
+ verifyInputViewStatusOnMainSync(
+ () -> assertThat(mActivity.hideImeWithInputMethodManager(0 /* flags */)).isTrue(),
+ true /* expected */,
+ false /* inputViewStarted */);
+ if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
+ // The IME visibility is only sent at the end of the animation. Therefore, we have to
+ // wait until the visibility was sent to the server and the IME window hidden.
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
+ } else {
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
}
@@ -179,39 +218,41 @@ public class InputMethodServiceTest {
* This checks that the IME can be shown and hidden using the WindowInsetsController APIs.
*/
@Test
- public void testShowHideKeyboard_byApi() throws Exception {
+ public void testShowHideKeyboard_byInsetsController() {
setShowImeWithHardKeyboard(true /* enabled */);
// Triggers to show IME via public API.
verifyInputViewStatusOnMainSync(
- () -> assertThat(mActivity.showImeWithWindowInsetsController()).isTrue(),
+ () -> mActivity.showImeWithWindowInsetsController(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
// Triggers to hide IME via public API.
verifyInputViewStatusOnMainSync(
- () -> assertThat(mActivity.hideImeWithWindowInsetsController()).isTrue(),
+ () -> mActivity.hideImeWithWindowInsetsController(),
true /* expected */,
false /* inputViewStarted */);
if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
} else {
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
}
/**
* This checks the result of calling IMS#requestShowSelf and IMS#requestHideSelf.
*
- * With the refactor in b/298172246, all calls to IMMS#{show,hide}MySoftInputLocked
+ * <p>With the refactor in b/298172246, all calls to IMMS#{show,hide}MySoftInputLocked
* will be just apply the requested visibility (by using the callback). Therefore, we will
* lose flags like HIDE_IMPLICIT_ONLY.
*/
@Test
- public void testShowHideSelf() throws Exception {
+ public void testShowHideSelf() {
setShowImeWithHardKeyboard(true /* enabled */);
// IME request to show itself without any flags, expect shown.
@@ -220,7 +261,7 @@ public class InputMethodServiceTest {
() -> mInputMethodService.requestShowSelf(0 /* flags */),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
if (!mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
// IME request to hide itself with flag HIDE_IMPLICIT_ONLY, expect not hide (shown).
@@ -230,7 +271,8 @@ public class InputMethodServiceTest {
InputMethodManager.HIDE_IMPLICIT_ONLY),
false /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown after HIDE_IMPLICIT_ONLY")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
}
// IME request to hide itself without any flags, expect hidden.
@@ -242,9 +284,11 @@ public class InputMethodServiceTest {
if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
} else {
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
if (!mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
@@ -254,7 +298,8 @@ public class InputMethodServiceTest {
() -> mInputMethodService.requestShowSelf(InputMethodManager.SHOW_IMPLICIT),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown with SHOW_IMPLICIT")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
// IME request to hide itself with flag HIDE_IMPLICIT_ONLY, expect hidden.
Log.i(TAG, "Call IMS#requestHideSelf(InputMethodManager.HIDE_IMPLICIT_ONLY)");
@@ -263,7 +308,8 @@ public class InputMethodServiceTest {
InputMethodManager.HIDE_IMPLICIT_ONLY),
true /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown after HIDE_IMPLICIT_ONLY")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
}
@@ -272,53 +318,60 @@ public class InputMethodServiceTest {
* when show_ime_with_hard_keyboard is enabled.
*/
@Test
- public void testOnEvaluateInputViewShown_showImeWithHardKeyboard() throws Exception {
+ public void testOnEvaluateInputViewShown_showImeWithHardKeyboard() {
setShowImeWithHardKeyboard(true /* enabled */);
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
+ eventually(() -> assertWithMessage("InputView should show with visible hardware keyboard")
+ .that(mInputMethodService.onEvaluateInputViewShown()).isTrue());
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_NOKEYS;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
+ eventually(() -> assertWithMessage("InputView should show without hardware keyboard")
+ .that(mInputMethodService.onEvaluateInputViewShown()).isTrue());
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_YES;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
+ eventually(() -> assertWithMessage("InputView should show with hidden hardware keyboard")
+ .that(mInputMethodService.onEvaluateInputViewShown()).isTrue());
}
/**
- * This checks the return value of IMSonEvaluateInputViewShown,
+ * This checks the return value of IMS#onEvaluateInputViewShown,
* when show_ime_with_hard_keyboard is disabled.
*/
@Test
- public void testOnEvaluateInputViewShown_disableShowImeWithHardKeyboard() throws Exception {
+ public void testOnEvaluateInputViewShown_disableShowImeWithHardKeyboard() {
setShowImeWithHardKeyboard(false /* enabled */);
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isFalse());
+ eventually(() ->
+ assertWithMessage("InputView should not show with visible hardware keyboard")
+ .that(mInputMethodService.onEvaluateInputViewShown()).isFalse());
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_NOKEYS;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
+ eventually(() -> assertWithMessage("InputView should show without hardware keyboard")
+ .that(mInputMethodService.onEvaluateInputViewShown()).isTrue());
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_YES;
- eventually(() -> assertThat(mInputMethodService.onEvaluateInputViewShown()).isTrue());
+ eventually(() -> assertWithMessage("InputView should show with hidden hardware keyboard")
+ .that(mInputMethodService.onEvaluateInputViewShown()).isTrue());
}
/**
@@ -326,51 +379,53 @@ public class InputMethodServiceTest {
* when IMS#onEvaluateInputViewShown returns false, results in the IME not being shown.
*/
@Test
- public void testShowSoftInput_disableShowImeWithHardKeyboard() throws Exception {
+ public void testShowSoftInput_disableShowImeWithHardKeyboard() {
setShowImeWithHardKeyboard(false /* enabled */);
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
Configuration.HARDKEYBOARDHIDDEN_NO;
- // When InputMethodService#onEvaluateInputViewShown() returns false, the Ime should not be
+ // When InputMethodService#onEvaluateInputViewShown() returns false, the IME should not be
// shown no matter what the show flag is.
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown after SHOW_IMPLICIT")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
verifyInputViewStatusOnMainSync(
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown after SHOW_EXPLICIT")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
/**
* This checks that an explicit show request results in the IME being shown.
*/
@Test
- public void testShowSoftInputExplicitly() throws Exception {
+ public void testShowSoftInputExplicitly() {
setShowImeWithHardKeyboard(true /* enabled */);
// When InputMethodService#onEvaluateInputViewShown() returns true and flag is EXPLICIT, the
- // Ime should be shown.
+ // IME should be shown.
verifyInputViewStatusOnMainSync(
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
* This checks that an implicit show request results in the IME being shown.
*/
@Test
- public void testShowSoftInputImplicitly() throws Exception {
+ public void testShowSoftInputImplicitly() {
setShowImeWithHardKeyboard(true /* enabled */);
// When InputMethodService#onEvaluateInputViewShown() returns true and flag is IMPLICIT,
@@ -379,7 +434,7 @@ public class InputMethodServiceTest {
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
@@ -387,73 +442,74 @@ public class InputMethodServiceTest {
* and it should be shown in fullscreen mode, results in the IME being shown.
*/
@Test
- public void testShowSoftInputExplicitly_fullScreenMode() throws Exception {
+ public void testShowSoftInputExplicitly_fullScreenMode() {
setShowImeWithHardKeyboard(true /* enabled */);
// Set orientation landscape to enable fullscreen mode.
setOrientation(2);
- eventually(() -> assertThat(mUiDevice.isNaturalOrientation()).isFalse());
+ eventually(() -> assertWithMessage("No longer in natural orientation")
+ .that(mUiDevice.isNaturalOrientation()).isFalse());
// Wait for the TestActivity to be recreated.
- eventually(() ->
- assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
+ eventually(() -> assertWithMessage("Activity was re-created after rotation")
+ .that(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
// Get the new TestActivity.
mActivity = TestActivity.getLastCreatedInstance();
- assertThat(mActivity).isNotNull();
- InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+ assertWithMessage("Re-created activity is not null").that(mActivity).isNotNull();
// Wait for the new EditText to be served by InputMethodManager.
- eventually(() -> assertThat(
- imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
+ eventually(() -> assertWithMessage("Has an input connection to the re-created Activity")
+ .that(mImm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
* This checks that an implicit show request when the IME is not previously shown,
* and it should be shown in fullscreen mode, results in the IME not being shown.
*
- * With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
+ * <p>With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
* will be redirected to InsetsController#{show,hide}. Therefore, we will lose flags like
* SHOW_IMPLICIT.
*/
@Test
@RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
- public void testShowSoftInputImplicitly_fullScreenMode() throws Exception {
+ public void testShowSoftInputImplicitly_fullScreenMode() {
setShowImeWithHardKeyboard(true /* enabled */);
// Set orientation landscape to enable fullscreen mode.
setOrientation(2);
- eventually(() -> assertThat(mUiDevice.isNaturalOrientation()).isFalse());
+ eventually(() -> assertWithMessage("No longer in natural orientation")
+ .that(mUiDevice.isNaturalOrientation()).isFalse());
// Wait for the TestActivity to be recreated.
- eventually(() ->
- assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
+ eventually(() -> assertWithMessage("Activity was re-created after rotation")
+ .that(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
// Get the new TestActivity.
mActivity = TestActivity.getLastCreatedInstance();
- assertThat(mActivity).isNotNull();
- InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
+ assertWithMessage("Re-created activity is not null").that(mActivity).isNotNull();
// Wait for the new EditText to be served by InputMethodManager.
- eventually(() -> assertThat(
- imm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
+ eventually(() -> assertWithMessage("Has an input connection to the re-created Activity")
+ .that(mImm.hasActiveInputConnection(mActivity.getEditText())).isTrue());
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
/**
- * This checks that an explicit show request when a hard keyboard is connected,
+ * This checks that an explicit show request when a hardware keyboard is connected,
* results in the IME being shown.
*/
@Test
- public void testShowSoftInputExplicitly_withHardKeyboard() throws Exception {
+ public void testShowSoftInputExplicitly_withHardKeyboard() {
setShowImeWithHardKeyboard(false /* enabled */);
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -463,23 +519,23 @@ public class InputMethodServiceTest {
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
- * This checks that an implicit show request when a hard keyboard is connected,
+ * This checks that an implicit show request when a hardware keyboard is connected,
* results in the IME not being shown.
*
- * With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
+ * <p>With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
* will be redirected to InsetsController#{show,hide}. Therefore, we will lose flags like
* SHOW_IMPLICIT.
*/
@Test
@RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
- public void testShowSoftInputImplicitly_withHardKeyboard() throws Exception {
+ public void testShowSoftInputImplicitly_withHardKeyboard() {
setShowImeWithHardKeyboard(false /* enabled */);
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -489,18 +545,19 @@ public class InputMethodServiceTest {
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
false /* expected */,
false /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
/**
- * This checks that an explicit show request followed by connecting a hard keyboard
+ * This checks that an explicit show request followed by connecting a hardware keyboard
* and a configuration change, still results in the IME being shown.
*/
@Test
- public void testShowSoftInputExplicitly_thenConfigurationChanged() throws Exception {
+ public void testShowSoftInputExplicitly_thenConfigurationChanged() {
setShowImeWithHardKeyboard(false /* enabled */);
- // Start with no hard keyboard.
+ // Start with no hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_NOKEYS;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -510,9 +567,9 @@ public class InputMethodServiceTest {
() -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -526,24 +583,25 @@ public class InputMethodServiceTest {
mInputMethodService.getResources().getConfiguration()),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown after a configuration change")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
- * This checks that an implicit show request followed by connecting a hard keyboard
+ * This checks that an implicit show request followed by connecting a hardware keyboard
* and a configuration change, does not trigger IMS#onFinishInputView,
* but results in the IME being hidden.
*
- * With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
+ * <p>With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
* will be redirected to InsetsController#{show,hide}. Therefore, we will lose flags like
* SHOW_IMPLICIT.
*/
@Test
@RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
- public void testShowSoftInputImplicitly_thenConfigurationChanged() throws Exception {
+ public void testShowSoftInputImplicitly_thenConfigurationChanged() {
setShowImeWithHardKeyboard(false /* enabled */);
- // Start with no hard keyboard.
+ // Start with no hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_NOKEYS;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -553,9 +611,9 @@ public class InputMethodServiceTest {
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().keyboard =
@@ -574,7 +632,8 @@ public class InputMethodServiceTest {
mInputMethodService.getResources().getConfiguration()),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown after a configuration change")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
/**
@@ -583,11 +642,10 @@ public class InputMethodServiceTest {
* (i.e. the implicit show request is treated as explicit).
*/
@Test
- public void testShowSoftInputExplicitly_thenShowSoftInputImplicitly_withHardKeyboard()
- throws Exception {
+ public void testShowSoftInputExplicitly_thenShowSoftInputImplicitly_withHardKeyboard() {
setShowImeWithHardKeyboard(false /* enabled */);
- // Simulate connecting a hard keyboard.
+ // Simulate connecting a hardware keyboard.
mInputMethodService.getResources().getConfiguration().keyboard =
Configuration.KEYBOARD_QWERTY;
mInputMethodService.getResources().getConfiguration().hardKeyboardHidden =
@@ -598,23 +656,25 @@ public class InputMethodServiceTest {
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
// Implicit show request.
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_IMPLICIT)).isTrue(),
false /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
// Simulate a fake configuration change to avoid triggering the recreation of TestActivity.
// This should now consider the implicit show request, but keep the state from the
- // explicit show request, and thus not hide the keyboard.
+ // explicit show request, and thus not hide the IME.
verifyInputViewStatusOnMainSync(() -> mInputMethodService.onConfigurationChanged(
mInputMethodService.getResources().getConfiguration()),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown after a configuration change")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
@@ -622,40 +682,42 @@ public class InputMethodServiceTest {
* and then a hide not always request, still results in the IME being shown
* (i.e. the explicit show request retains the forced state).
*
- * With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
+ * <p>With the refactor in b/298172246, all calls from InputMethodManager#{show,hide}SoftInput
* will be redirected to InsetsController#{show,hide}. Therefore, we will lose flags like
* HIDE_NOT_ALWAYS.
*/
@Test
@RequiresFlagsDisabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)
- public void testShowSoftInputForced_testShowSoftInputExplicitly_thenHideSoftInputNotAlways()
- throws Exception {
+ public void testShowSoftInputForced_testShowSoftInputExplicitly_thenHideSoftInputNotAlways() {
setShowImeWithHardKeyboard(true /* enabled */);
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(InputMethodManager.SHOW_FORCED)).isTrue(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
verifyInputViewStatusOnMainSync(() -> assertThat(
mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
false /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
- verifyInputViewStatusOnMainSync(() ->
- mActivity.hideImeWithInputMethodManager(InputMethodManager.HIDE_NOT_ALWAYS),
+ verifyInputViewStatusOnMainSync(() -> assertThat(
+ mActivity.hideImeWithInputMethodManager(InputMethodManager.HIDE_NOT_ALWAYS))
+ .isTrue(),
false /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown after HIDE_NOT_ALWAYS")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
}
/**
* This checks that the IME fullscreen mode state is updated after changing orientation.
*/
@Test
- public void testFullScreenMode() throws Exception {
+ public void testFullScreenMode() {
setShowImeWithHardKeyboard(true /* enabled */);
Log.i(TAG, "Set orientation natural");
@@ -679,13 +741,13 @@ public class InputMethodServiceTest {
* then the IME caption bar is also not created.
*/
@Test
- public void testNoNavigationBar_thenImeNoCaptionBar() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeFalse("Must not have a navigation bar", hasNavigationBar);
+ public void testNoNavigationBar_thenImeNoCaptionBar() {
+ assumeFalse("Must not have a navigation bar", hasNavigationBar());
- assertEquals(Insets.NONE, mInputMethodService.getWindow().getWindow().getDecorView()
- .getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()));
+ assertWithMessage("No IME caption bar insets")
+ .that(mInputMethodService.getWindow().getWindow().getDecorView()
+ .getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()))
+ .isEqualTo(Insets.NONE);
}
/**
@@ -693,112 +755,104 @@ public class InputMethodServiceTest {
* when the IME does draw the IME navigation bar.
*/
@Test
- public void testShowHideImeNavigationBar_doesDrawImeNavBar() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeTrue("Must have a navigation bar", hasNavigationBar);
+ public void testShowHideImeNavigationBar_doesDrawImeNavBar() {
+ assumeTrue("Must have a navigation bar", hasNavigationBar());
setShowImeWithHardKeyboard(true /* enabled */);
// Show IME
verifyInputViewStatusOnMainSync(
() -> {
- mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
- InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR
- | InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN
- );
- assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue();
+ setDrawsImeNavBarAndSwitcherButton(true /* enabled */);
+ mActivity.showImeWithWindowInsetsController();
},
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME navigation bar is initially shown")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue();
// Try to hide IME nav bar
- mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
- .getInsetsController().hide(captionBar()));
+ mInstrumentation.runOnMainSync(() -> setShowImeNavigationBar(false /* show */));
mInstrumentation.waitForIdleSync();
- assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+ assertWithMessage("IME navigation bar is not shown after hide request")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
// Try to show IME nav bar
- mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
- .getInsetsController().show(captionBar()));
+ mInstrumentation.runOnMainSync(() -> setShowImeNavigationBar(true /* show */));
mInstrumentation.waitForIdleSync();
- assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue();
+ assertWithMessage("IME navigation bar is shown after show request")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue();
}
+
/**
* This checks that trying to show and hide the navigation bar has no effect
* when the IME does not draw the IME navigation bar.
*
- * Note: The IME navigation bar is *never* visible in 3 button navigation mode.
+ * <p>Note: The IME navigation bar is *never* visible in 3 button navigation mode.
*/
@Test
- public void testShowHideImeNavigationBar_doesNotDrawImeNavBar() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeTrue("Must have a navigation bar", hasNavigationBar);
+ public void testShowHideImeNavigationBar_doesNotDrawImeNavBar() {
+ assumeTrue("Must have a navigation bar", hasNavigationBar());
setShowImeWithHardKeyboard(true /* enabled */);
// Show IME
- verifyInputViewStatusOnMainSync(() -> {
- mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
- 0 /* navButtonFlags */);
- assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue();
- },
+ verifyInputViewStatusOnMainSync(
+ () -> {
+ setDrawsImeNavBarAndSwitcherButton(false /* enabled */);
+ mActivity.showImeWithWindowInsetsController();
+ },
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME navigation bar is initially not shown")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
// Try to hide IME nav bar
- mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
- .getInsetsController().hide(captionBar()));
+ mInstrumentation.runOnMainSync(() -> setShowImeNavigationBar(false /* show */));
mInstrumentation.waitForIdleSync();
- assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+ assertWithMessage("IME navigation bar is not shown after hide request")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
// Try to show IME nav bar
- mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
- .getInsetsController().show(captionBar()));
+ mInstrumentation.runOnMainSync(() -> setShowImeNavigationBar(true /* show */));
mInstrumentation.waitForIdleSync();
- assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+ assertWithMessage("IME navigation bar is not shown after show request")
+ .that(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
}
/**
* Verifies that clicking on the IME navigation bar back button hides the IME.
*/
@Test
- public void testBackButtonClick() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeTrue("Must have a navigation bar", hasNavigationBar);
+ public void testBackButtonClick() {
+ assumeTrue("Must have a navigation bar", hasNavigationBar());
assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled());
setShowImeWithHardKeyboard(true /* enabled */);
verifyInputViewStatusOnMainSync(
() -> {
- // Ensure the IME navigation bar and the IME switch button are drawn.
- mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
- InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR
- | InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN
- );
- assertThat(mActivity.showImeWithWindowInsetsController()).isTrue();
+ setDrawsImeNavBarAndSwitcherButton(true /* enabled */);
+ mActivity.showImeWithWindowInsetsController();
},
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- final var backButtonUiObject = getUiObjectById(INPUT_METHOD_NAV_BACK_ID);
+ final var backButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID));
backButtonUiObject.click();
mInstrumentation.waitForIdleSync();
if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
} else {
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
}
@@ -806,37 +860,33 @@ public class InputMethodServiceTest {
* Verifies that long clicking on the IME navigation bar back button hides the IME.
*/
@Test
- public void testBackButtonLongClick() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeTrue("Must have a navigation bar", hasNavigationBar);
+ public void testBackButtonLongClick() {
+ assumeTrue("Must have a navigation bar", hasNavigationBar());
assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled());
setShowImeWithHardKeyboard(true /* enabled */);
verifyInputViewStatusOnMainSync(
() -> {
- // Ensure the IME navigation bar and the IME switch button are drawn.
- mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
- InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR
- | InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN
- );
- assertThat(mActivity.showImeWithWindowInsetsController()).isTrue();
+ setDrawsImeNavBarAndSwitcherButton(true /* enabled */);
+ mActivity.showImeWithWindowInsetsController();
},
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- final var backButtonUiObject = getUiObjectById(INPUT_METHOD_NAV_BACK_ID);
+ final var backButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID));
backButtonUiObject.longClick();
mInstrumentation.waitForIdleSync();
if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
} else {
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
}
@@ -845,43 +895,37 @@ public class InputMethodServiceTest {
* or switches the input method.
*/
@Test
- public void testImeSwitchButtonClick() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeTrue("Must have a navigation bar", hasNavigationBar);
+ public void testImeSwitchButtonClick() {
+ assumeTrue("Must have a navigation bar", hasNavigationBar());
assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled());
setShowImeWithHardKeyboard(true /* enabled */);
verifyInputViewStatusOnMainSync(
() -> {
- // Ensure the IME navigation bar and the IME switch button are drawn.
- mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
- InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR
- | InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN
- );
- assertThat(mActivity.showImeWithWindowInsetsController()).isTrue();
+ setDrawsImeNavBarAndSwitcherButton(true /* enabled */);
+ mActivity.showImeWithWindowInsetsController();
},
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- final var imm = mContext.getSystemService(InputMethodManager.class);
- final var initialInfo = imm.getCurrentInputMethodInfo();
+ final var initialInfo = mImm.getCurrentInputMethodInfo();
- final var imeSwitchButtonUiObject = getUiObjectById(INPUT_METHOD_NAV_IME_SWITCHER_ID);
+ final var imeSwitchButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID));
imeSwitchButtonUiObject.click();
mInstrumentation.waitForIdleSync();
- final var newInfo = imm.getCurrentInputMethodInfo();
+ final var newInfo = mImm.getCurrentInputMethodInfo();
assertWithMessage("Input Method Switcher Menu is shown or input method was switched")
- .that(isInputMethodPickerShown(imm) || !Objects.equals(initialInfo, newInfo))
+ .that(isInputMethodPickerShown(mImm) || !Objects.equals(initialInfo, newInfo))
.isTrue();
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is still shown after IME Switcher button was clicked")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
- // Hide the Picker menu before finishing.
+ // Hide the IME Switcher Menu before finishing.
mUiDevice.pressBack();
}
@@ -889,58 +933,42 @@ public class InputMethodServiceTest {
* Verifies that long clicking on the IME switch button shows the Input Method Switcher Menu.
*/
@Test
- public void testImeSwitchButtonLongClick() throws Exception {
- boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
- .hasNavigationBar(mInputMethodService.getDisplayId());
- assumeTrue("Must have a navigation bar", hasNavigationBar);
+ public void testImeSwitchButtonLongClick() {
+ assumeTrue("Must have a navigation bar", hasNavigationBar());
assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled());
setShowImeWithHardKeyboard(true /* enabled */);
verifyInputViewStatusOnMainSync(
() -> {
- // Ensure the IME navigation bar and the IME switch button are drawn.
- mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
- InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR
- | InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN
- );
- assertThat(mActivity.showImeWithWindowInsetsController()).isTrue();
+ setDrawsImeNavBarAndSwitcherButton(true /* enabled */);
+ mActivity.showImeWithWindowInsetsController();
},
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- final var imm = mContext.getSystemService(InputMethodManager.class);
-
- final var imeSwitchButtonUiObject = getUiObjectById(INPUT_METHOD_NAV_IME_SWITCHER_ID);
+ final var imeSwitchButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID));
imeSwitchButtonUiObject.longClick();
mInstrumentation.waitForIdleSync();
assertWithMessage("Input Method Switcher Menu is shown")
- .that(isInputMethodPickerShown(imm))
- .isTrue();
- if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
- // The IME visibility is only sent at the end of the animation. Therefore, we have to
- // wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
- } else {
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- }
+ .that(isInputMethodPickerShown(mImm)).isTrue();
+ assertWithMessage("IME is still shown after IME Switcher button was long clicked")
+ .that(mInputMethodService.isInputViewShown()).isTrue();
- // Hide the Picker menu before finishing.
+ // Hide the IME Switcher Menu before finishing.
mUiDevice.pressBack();
}
- private void verifyInputViewStatus(
- Runnable runnable, boolean expected, boolean inputViewStarted)
- throws InterruptedException {
+ private void verifyInputViewStatus(@NonNull Runnable runnable, boolean expected,
+ boolean inputViewStarted) {
verifyInputViewStatusInternal(runnable, expected, inputViewStarted,
false /* runOnMainSync */);
}
- private void verifyInputViewStatusOnMainSync(
- Runnable runnable, boolean expected, boolean inputViewStarted)
- throws InterruptedException {
+ private void verifyInputViewStatusOnMainSync(@NonNull Runnable runnable, boolean expected,
+ boolean inputViewStarted) {
verifyInputViewStatusInternal(runnable, expected, inputViewStarted,
true /* runOnMainSync */);
}
@@ -948,24 +976,32 @@ public class InputMethodServiceTest {
/**
* Verifies the status of the Input View after executing the given runnable.
*
- * @param runnable the runnable to execute for showing or hiding the IME.
- * @param expected whether the runnable is expected to trigger the signal.
+ * @param runnable the runnable to execute for showing or hiding the IME.
+ * @param expected whether the runnable is expected to trigger the signal.
* @param inputViewStarted the expected state of the Input View after executing the runnable.
- * @param runOnMainSync whether to execute the runnable on the main thread.
+ * @param runOnMainSync whether to execute the runnable on the main thread.
*/
- private void verifyInputViewStatusInternal(
- Runnable runnable, boolean expected, boolean inputViewStarted, boolean runOnMainSync)
- throws InterruptedException {
- CountDownLatch signal = new CountDownLatch(1);
- mInputMethodService.setCountDownLatchForTesting(signal);
- // Runnable to trigger onStartInputView() / onFinishInputView() / onConfigurationChanged()
- if (runOnMainSync) {
- mInstrumentation.runOnMainSync(runnable);
- } else {
- runnable.run();
+ private void verifyInputViewStatusInternal(@NonNull Runnable runnable, boolean expected,
+ boolean inputViewStarted, boolean runOnMainSync) {
+ final boolean completed;
+ try {
+ final var latch = new CountDownLatch(1);
+ mInputMethodService.setCountDownLatchForTesting(latch);
+ // Trigger onStartInputView() / onFinishInputView() / onConfigurationChanged()
+ if (runOnMainSync) {
+ mInstrumentation.runOnMainSync(runnable);
+ } else {
+ runnable.run();
+ }
+ mInstrumentation.waitForIdleSync();
+ completed = latch.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ fail("Interrupted while waiting for latch: " + e.getMessage());
+ return;
+ } finally {
+ mInputMethodService.setCountDownLatchForTesting(null);
}
- mInstrumentation.waitForIdleSync();
- boolean completed = signal.await(TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
+
if (expected && !completed) {
fail("Timed out waiting for"
+ " onStartInputView() / onFinishInputView() / onConfigurationChanged()");
@@ -974,8 +1010,10 @@ public class InputMethodServiceTest {
+ " onStartInputView() / onFinishInputView() / onConfigurationChanged()");
}
// Input is not finished.
- assertThat(mInputMethodService.getCurrentInputStarted()).isTrue();
- assertThat(mInputMethodService.getCurrentInputViewStarted()).isEqualTo(inputViewStarted);
+ assertWithMessage("Input connection is still started")
+ .that(mInputMethodService.getCurrentInputStarted()).isTrue();
+ assertWithMessage("IME visibility matches expected")
+ .that(mInputMethodService.getCurrentInputViewStarted()).isEqualTo(inputViewStarted);
}
private void setOrientation(int orientation) {
@@ -999,37 +1037,45 @@ public class InputMethodServiceTest {
/**
* Verifies the IME fullscreen mode state after executing the given runnable.
*
- * @param runnable the runnable to execute for setting the orientation.
- * @param expected whether the runnable is expected to trigger the signal.
+ * @param runnable the runnable to execute for setting the orientation.
+ * @param expected whether the runnable is expected to trigger the signal.
* @param orientationPortrait whether the orientation is expected to be portrait.
*/
private void verifyFullscreenMode(@NonNull Runnable runnable, boolean expected,
- boolean orientationPortrait) throws InterruptedException {
+ boolean orientationPortrait) {
verifyInputViewStatus(runnable, expected, false /* inputViewStarted */);
if (expected) {
// Wait for the TestActivity to be recreated.
- eventually(() ->
- assertThat(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
+ eventually(() -> assertWithMessage("Activity was re-created after rotation")
+ .that(TestActivity.getLastCreatedInstance()).isNotEqualTo(mActivity));
// Get the new TestActivity.
mActivity = TestActivity.getLastCreatedInstance();
+ assertWithMessage("Re-created activity is not null").that(mActivity).isNotNull();
}
verifyInputViewStatusOnMainSync(
() -> mActivity.showImeWithWindowInsetsController(),
true /* expected */,
true /* inputViewStarted */);
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue();
- assertThat(mInputMethodService.getResources().getConfiguration().orientation)
+ assertWithMessage("IME orientation matches expected")
+ .that(mInputMethodService.getResources().getConfiguration().orientation)
.isEqualTo(orientationPortrait
? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE);
- EditorInfo editorInfo = mInputMethodService.getCurrentInputEditorInfo();
- assertThat(editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN).isEqualTo(0);
- assertThat(editorInfo.internalImeOptions & EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT)
+ final var editorInfo = mInputMethodService.getCurrentInputEditorInfo();
+ assertWithMessage("IME_FLAG_NO_FULLSCREEN not set")
+ .that(editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN).isEqualTo(0);
+ assertWithMessage("IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT matches expected")
+ .that(editorInfo.internalImeOptions
+ & EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT)
.isEqualTo(
orientationPortrait ? EditorInfo.IME_INTERNAL_FLAG_APP_WINDOW_PORTRAIT : 0);
- assertThat(mInputMethodService.onEvaluateFullscreenMode()).isEqualTo(!orientationPortrait);
- assertThat(mInputMethodService.isFullscreenMode()).isEqualTo(!orientationPortrait);
+ assertWithMessage("onEvaluateFullscreenMode matches orientation")
+ .that(mInputMethodService.onEvaluateFullscreenMode())
+ .isEqualTo(!orientationPortrait);
+ assertWithMessage("isFullscreenMode matches orientation")
+ .that(mInputMethodService.isFullscreenMode()).isEqualTo(!orientationPortrait);
// Hide IME before finishing the run.
verifyInputViewStatusOnMainSync(
@@ -1040,24 +1086,27 @@ public class InputMethodServiceTest {
if (mFlagsValueProvider.getBoolean(Flags.FLAG_REFACTOR_INSETS_CONTROLLER)) {
// The IME visibility is only sent at the end of the animation. Therefore, we have to
// wait until the visibility was sent to the server and the IME window hidden.
- eventually(() -> assertThat(mInputMethodService.isInputViewShown()).isFalse());
+ eventually(() -> assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse());
} else {
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
+ assertWithMessage("IME is not shown")
+ .that(mInputMethodService.isInputViewShown()).isFalse();
}
}
- private void prepareIme() throws Exception {
+ private void prepareIme() {
executeShellCommand("ime enable " + mInputMethodId);
executeShellCommand("ime set " + mInputMethodId);
mInstrumentation.waitForIdleSync();
Log.i(TAG, "Finish preparing IME");
}
- private void prepareEditor() {
- mActivity = TestActivity.start(mInstrumentation);
+ private void prepareActivity() {
+ mActivity = TestActivity.startSync(mInstrumentation);
Log.i(TAG, "Finish preparing activity with editor.");
}
+ @NonNull
private String getInputMethodId() {
return mTargetPackageName + "/" + INPUT_METHOD_SERVICE_NAME;
}
@@ -1067,7 +1116,7 @@ public class InputMethodServiceTest {
*
* @param enabled the value to be set.
*/
- private void setShowImeWithHardKeyboard(boolean enabled) throws IOException {
+ private void setShowImeWithHardKeyboard(boolean enabled) {
if (mShowImeWithHardKeyboardEnabled != enabled) {
executeShellCommand(enabled
? ENABLE_SHOW_IME_WITH_HARD_KEYBOARD_CMD
@@ -1076,9 +1125,9 @@ public class InputMethodServiceTest {
}
}
- private String executeShellCommand(String cmd) throws IOException {
+ private static void executeShellCommand(@NonNull String cmd) {
Log.i(TAG, "Run command: " + cmd);
- return SystemUtil.runShellCommandOrThrow(cmd);
+ SystemUtil.runShellCommandOrThrow(cmd);
}
/**
@@ -1090,31 +1139,63 @@ public class InputMethodServiceTest {
}
@NonNull
- private UiObject2 getUiObjectById(@NonNull String id) {
- final var uiObject = mUiDevice.wait(
- Until.findObject(By.res(id)),
+ private UiObject2 getUiObject(@NonNull BySelector bySelector) {
+ final var uiObject = mUiDevice.wait(Until.findObject(bySelector),
TimeUnit.SECONDS.toMillis(TIMEOUT_IN_SECONDS));
- assertThat(uiObject).isNotNull();
+ assertWithMessage("UiObject with " + bySelector + " was found").that(uiObject).isNotNull();
return uiObject;
}
- /**
- * Returns {@code true} if the navigation mode is gesture nav, and {@code false} otherwise.
- */
+ /** Checks whether gesture navigation move is enabled. */
private boolean isGestureNavEnabled() {
return mContext.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode)
== WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
}
- private void clickOnEditorText() {
+ /** Checks whether the device has a navigation bar on the IME's display. */
+ private boolean hasNavigationBar() {
+ try {
+ return WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ } catch (RemoteException e) {
+ fail("Failed to check whether the device has a navigation bar: " + e.getMessage());
+ return false;
+ }
+ }
+
+ /**
+ * Manually sets whether the IME draws the IME navigation bar and IME Switcher button,
+ * regardless of the current navigation bar mode.
+ *
+ * <p>Note, neither of these are normally drawn when in three button navigation mode.
+ *
+ * @param enabled whether the IME nav bar and IME Switcher button are drawn.
+ */
+ private void setDrawsImeNavBarAndSwitcherButton(boolean enabled) {
+ final int flags = enabled ? IME_DRAWS_IME_NAV_BAR | SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN : 0;
+ mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(flags);
+ }
+
+ /**
+ * Set whether the IME navigation bar should be shown or not.
+ *
+ * <p>Note, this has no effect when the IME does not draw the IME navigation bar.
+ *
+ * @param show whether the IME navigation bar should be shown.
+ */
+ private void setShowImeNavigationBar(boolean show) {
+ final var controller = mInputMethodService.getWindow().getWindow().getInsetsController();
+ if (show) {
+ controller.show(captionBar());
+ } else {
+ controller.hide(captionBar());
+ }
+ }
+
+ private void clickOnEditText() {
// Find the editText and click it.
- UiObject2 editTextUiObject =
- mUiDevice.wait(
- Until.findObject(By.desc(EDIT_TEXT_DESC)),
- TimeUnit.SECONDS.toMillis(TIMEOUT_IN_SECONDS));
- assertThat(editTextUiObject).isNotNull();
- editTextUiObject.click();
+ getUiObject(By.desc(EDIT_TEXT_DESC)).click();
mInstrumentation.waitForIdleSync();
}
}
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleInputMethodService.java b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleInputMethodService.java
index 48942a31658f..61d1bb931a96 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleInputMethodService.java
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleInputMethodService.java
@@ -23,13 +23,15 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+
import com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper;
-/** The {@link InputMethodService} implementation for SimpeTestIme app. */
-public class SimpleInputMethodService extends InputMethodServiceWrapper {
+/** The {@link InputMethodService} implementation for SimpleTestIme app. */
+public final class SimpleInputMethodService extends InputMethodServiceWrapper {
+
private static final String TAG = "SimpleIMS";
private FrameLayout mInputView;
@@ -45,23 +47,18 @@ public class SimpleInputMethodService extends InputMethodServiceWrapper {
public void onStartInputView(EditorInfo info, boolean restarting) {
super.onStartInputView(info, restarting);
mInputView.removeAllViews();
- SimpleKeyboard keyboard = new SimpleKeyboard(this, R.layout.qwerty_10_9_9);
+ final var keyboard = new SimpleKeyboard(this, R.layout.qwerty_10_9_9);
mInputView.addView(keyboard.inflateKeyboardView(LayoutInflater.from(this), mInputView));
}
- void handle(String data, int keyboardState) {
- InputConnection inputConnection = getCurrentInputConnection();
- Integer keyCode = KeyCodeConstants.KEY_NAME_TO_CODE_MAP.get(data);
+ void handleKeyPress(@NonNull String keyCodeName, int keyboardState) {
+ final Integer keyCode = KeyCodeConstants.KEY_NAME_TO_CODE_MAP.get(keyCodeName);
Log.v(TAG, "keyCode: " + keyCode);
if (keyCode != null) {
- inputConnection.sendKeyEvent(
- new KeyEvent(
- SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(),
- KeyEvent.ACTION_DOWN,
- keyCode,
- 0,
- KeyCodeConstants.isAlphaKeyCode(keyCode) ? keyboardState : 0));
+ final var downTime = SystemClock.uptimeMillis();
+ getCurrentInputConnection().sendKeyEvent(new KeyEvent(downTime, downTime,
+ KeyEvent.ACTION_DOWN, keyCode, 0 /* repeat */,
+ KeyCodeConstants.isAlphaKeyCode(keyCode) ? keyboardState : 0) /* metaState */);
}
}
}
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleKeyboard.java b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleKeyboard.java
index b16ec9ebd718..62d90c8d56b5 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleKeyboard.java
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SimpleKeyboard.java
@@ -25,60 +25,65 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
/** Controls the visible virtual keyboard view. */
final class SimpleKeyboard {
+
private static final String TAG = "SimpleKeyboard";
- private static final int[] SOFT_KEY_IDS =
- new int[] {
- R.id.key_pos_0_0,
- R.id.key_pos_0_1,
- R.id.key_pos_0_2,
- R.id.key_pos_0_3,
- R.id.key_pos_0_4,
- R.id.key_pos_0_5,
- R.id.key_pos_0_6,
- R.id.key_pos_0_7,
- R.id.key_pos_0_8,
- R.id.key_pos_0_9,
- R.id.key_pos_1_0,
- R.id.key_pos_1_1,
- R.id.key_pos_1_2,
- R.id.key_pos_1_3,
- R.id.key_pos_1_4,
- R.id.key_pos_1_5,
- R.id.key_pos_1_6,
- R.id.key_pos_1_7,
- R.id.key_pos_1_8,
- R.id.key_pos_2_0,
- R.id.key_pos_2_1,
- R.id.key_pos_2_2,
- R.id.key_pos_2_3,
- R.id.key_pos_2_4,
- R.id.key_pos_2_5,
- R.id.key_pos_2_6,
- R.id.key_pos_shift,
- R.id.key_pos_del,
- R.id.key_pos_symbol,
- R.id.key_pos_comma,
- R.id.key_pos_space,
- R.id.key_pos_period,
- R.id.key_pos_enter,
- };
+ private static final int[] SOFT_KEY_IDS = new int[]{
+ R.id.key_pos_0_0,
+ R.id.key_pos_0_1,
+ R.id.key_pos_0_2,
+ R.id.key_pos_0_3,
+ R.id.key_pos_0_4,
+ R.id.key_pos_0_5,
+ R.id.key_pos_0_6,
+ R.id.key_pos_0_7,
+ R.id.key_pos_0_8,
+ R.id.key_pos_0_9,
+ R.id.key_pos_1_0,
+ R.id.key_pos_1_1,
+ R.id.key_pos_1_2,
+ R.id.key_pos_1_3,
+ R.id.key_pos_1_4,
+ R.id.key_pos_1_5,
+ R.id.key_pos_1_6,
+ R.id.key_pos_1_7,
+ R.id.key_pos_1_8,
+ R.id.key_pos_2_0,
+ R.id.key_pos_2_1,
+ R.id.key_pos_2_2,
+ R.id.key_pos_2_3,
+ R.id.key_pos_2_4,
+ R.id.key_pos_2_5,
+ R.id.key_pos_2_6,
+ R.id.key_pos_shift,
+ R.id.key_pos_del,
+ R.id.key_pos_symbol,
+ R.id.key_pos_comma,
+ R.id.key_pos_space,
+ R.id.key_pos_period,
+ R.id.key_pos_enter,
+ };
+ @NonNull
private final SimpleInputMethodService mSimpleInputMethodService;
private final int mViewResId;
private final SparseArray<TextView> mSoftKeyViews = new SparseArray<>();
private View mKeyboardView;
private int mKeyboardState;
- SimpleKeyboard(SimpleInputMethodService simpleInputMethodService, int viewResId) {
- this.mSimpleInputMethodService = simpleInputMethodService;
- this.mViewResId = viewResId;
- this.mKeyboardState = 0;
+ SimpleKeyboard(@NonNull SimpleInputMethodService simpleInputMethodService, int viewResId) {
+ mSimpleInputMethodService = simpleInputMethodService;
+ mViewResId = viewResId;
+ mKeyboardState = 0;
}
- View inflateKeyboardView(LayoutInflater inflater, ViewGroup inputView) {
+ @NonNull
+ View inflateKeyboardView(@NonNull LayoutInflater inflater, @NonNull ViewGroup inputView) {
mKeyboardView = inflater.inflate(mViewResId, inputView, false);
mapSoftKeys();
return mKeyboardView;
@@ -86,30 +91,31 @@ final class SimpleKeyboard {
private void mapSoftKeys() {
for (int id : SOFT_KEY_IDS) {
- TextView softKeyView = mKeyboardView.findViewById(id);
+ final TextView softKeyView = mKeyboardView.requireViewById(id);
mSoftKeyViews.put(id, softKeyView);
- String tagData = softKeyView.getTag() != null ? softKeyView.getTag().toString() : null;
- softKeyView.setOnClickListener(v -> handle(tagData));
+ final var keyCodeName = softKeyView.getTag() != null
+ ? softKeyView.getTag().toString() : null;
+ softKeyView.setOnClickListener(v -> handleKeyPress(keyCodeName));
}
}
- private void handle(String data) {
- Log.i(TAG, "handle(): " + data);
- if (TextUtils.isEmpty(data)) {
+ private void handleKeyPress(@Nullable String keyCodeName) {
+ Log.i(TAG, "handle(): " + keyCodeName);
+ if (TextUtils.isEmpty(keyCodeName)) {
return;
}
- if ("KEYCODE_SHIFT".equals(data)) {
+ if ("KEYCODE_SHIFT".equals(keyCodeName)) {
handleShift();
return;
}
- mSimpleInputMethodService.handle(data, mKeyboardState);
+ mSimpleInputMethodService.handleKeyPress(keyCodeName, mKeyboardState);
}
private void handleShift() {
mKeyboardState = toggleShiftState(mKeyboardState);
Log.v(TAG, "currentKeyboardState: " + mKeyboardState);
- boolean isShiftOn = isShiftOn(mKeyboardState);
+ final boolean isShiftOn = isShiftOn(mKeyboardState);
for (int i = 0; i < mSoftKeyViews.size(); i++) {
TextView softKeyView = mSoftKeyViews.valueAt(i);
softKeyView.setAllCaps(isShiftOn);
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/ims/InputMethodServiceWrapper.java b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/ims/InputMethodServiceWrapper.java
index 67212b60f1b8..be59dd2cb7a3 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/ims/InputMethodServiceWrapper.java
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/ims/InputMethodServiceWrapper.java
@@ -25,21 +25,35 @@ import java.util.concurrent.CountDownLatch;
/** Wrapper of {@link InputMethodService} to expose interfaces for testing purpose. */
public class InputMethodServiceWrapper extends InputMethodService {
- private static final String TAG = "InputMethodServiceWrapper";
- private static InputMethodServiceWrapper sInputMethodServiceWrapper;
+ private static final String TAG = "InputMethodServiceWrapper";
- public static InputMethodServiceWrapper getInputMethodServiceWrapperForTesting() {
- return sInputMethodServiceWrapper;
- }
+ /** Last created instance of this wrapper. */
+ private static InputMethodServiceWrapper sInstance;
private boolean mInputViewStarted;
+
+ /**
+ * @see #setCountDownLatchForTesting
+ */
private CountDownLatch mCountDownLatchForTesting;
+ /** Gets the last created instance of this wrapper, if available. */
+ public static InputMethodServiceWrapper getInstance() {
+ return sInstance;
+ }
+
public boolean getCurrentInputViewStarted() {
return mInputViewStarted;
}
+ /**
+ * Sets the latch used to wait for the IME to start showing ({@link #onStartInputView},
+ * start hiding ({@link #onFinishInputView}) or receive a configuration change
+ * ({@link #onConfigurationChanged}).
+ *
+ * @param countDownLatchForTesting the latch to wait on.
+ */
public void setCountDownLatchForTesting(CountDownLatch countDownLatchForTesting) {
mCountDownLatchForTesting = countDownLatchForTesting;
}
@@ -48,7 +62,7 @@ public class InputMethodServiceWrapper extends InputMethodService {
public void onCreate() {
Log.i(TAG, "onCreate()");
super.onCreate();
- sInputMethodServiceWrapper = this;
+ sInstance = this;
}
@Override
@@ -102,12 +116,13 @@ public class InputMethodServiceWrapper extends InputMethodService {
}
private String dumpEditorInfo(EditorInfo info) {
- var sb = new StringBuilder();
- sb.append("EditorInfo{packageName=").append(info.packageName);
- sb.append(" fieldId=").append(info.fieldId);
- sb.append(" hintText=").append(info.hintText);
- sb.append(" privateImeOptions=").append(info.privateImeOptions);
- sb.append("}");
- return sb.toString();
+ if (info == null) {
+ return "null";
+ }
+ return "EditorInfo{packageName=" + info.packageName
+ + " fieldId=" + info.fieldId
+ + " hintText=" + info.hintText
+ + " privateImeOptions=" + info.privateImeOptions
+ + "}";
}
}
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java
index 37b05ff79977..5a73ed5b25e1 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java
@@ -25,12 +25,12 @@ import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowInsets;
-import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.lang.ref.WeakReference;
@@ -42,10 +42,10 @@ import java.lang.ref.WeakReference;
* in the instruments package. More details see {@link
* Instrumentation#startActivitySync(Intent)}.</>
*/
-public class TestActivity extends Activity {
+public final class TestActivity extends Activity {
+
private static final String TAG = "TestActivity";
- private static WeakReference<TestActivity> sLastCreatedInstance =
- new WeakReference<>(null);
+ private static WeakReference<TestActivity> sLastCreatedInstance = new WeakReference<>(null);
/**
* Start a new test activity with an editor and wait for it to begin running before returning.
@@ -53,13 +53,13 @@ public class TestActivity extends Activity {
* @param instrumentation application instrumentation
* @return the newly started activity
*/
- public static TestActivity start(Instrumentation instrumentation) {
- Intent intent =
- new Intent()
- .setAction(Intent.ACTION_MAIN)
- .setClass(instrumentation.getTargetContext(), TestActivity.class)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ @NonNull
+ public static TestActivity startSync(@NonNull Instrumentation instrumentation) {
+ final var intent = new Intent()
+ .setAction(Intent.ACTION_MAIN)
+ .setClass(instrumentation.getTargetContext(), TestActivity.class)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return (TestActivity) instrumentation.startActivitySync(intent);
}
@@ -70,10 +70,10 @@ public class TestActivity extends Activity {
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
- LinearLayout rootView = new LinearLayout(this);
+ final var rootView = new LinearLayout(this);
mEditText = new EditText(this);
mEditText.setContentDescription("Input box");
rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
@@ -83,40 +83,39 @@ public class TestActivity extends Activity {
sLastCreatedInstance = new WeakReference<>(this);
}
- /** Get the last created TestActivity instance. */
- public static @Nullable TestActivity getLastCreatedInstance() {
+ /** Get the last created TestActivity instance, if available. */
+ @Nullable
+ public static TestActivity getLastCreatedInstance() {
return sLastCreatedInstance.get();
}
/** Shows soft keyboard via InputMethodManager. */
public boolean showImeWithInputMethodManager(int flags) {
- InputMethodManager imm = getSystemService(InputMethodManager.class);
- boolean result = imm.showSoftInput(mEditText, flags);
+ final var imm = getSystemService(InputMethodManager.class);
+ final boolean result = imm.showSoftInput(mEditText, flags);
Log.i(TAG, "showIme() via InputMethodManager, result=" + result);
return result;
}
/** Shows soft keyboard via WindowInsetsController. */
- public boolean showImeWithWindowInsetsController() {
- WindowInsetsController windowInsetsController = mEditText.getWindowInsetsController();
- windowInsetsController.show(WindowInsets.Type.ime());
+ public void showImeWithWindowInsetsController() {
+ final var controller = mEditText.getWindowInsetsController();
+ controller.show(WindowInsets.Type.ime());
Log.i(TAG, "showIme() via WindowInsetsController");
- return true;
}
/** Hides soft keyboard via InputMethodManager. */
public boolean hideImeWithInputMethodManager(int flags) {
- InputMethodManager imm = getSystemService(InputMethodManager.class);
- boolean result = imm.hideSoftInputFromWindow(mEditText.getWindowToken(), flags);
+ final var imm = getSystemService(InputMethodManager.class);
+ final boolean result = imm.hideSoftInputFromWindow(mEditText.getWindowToken(), flags);
Log.i(TAG, "hideIme() via InputMethodManager, result=" + result);
return result;
}
/** Hides soft keyboard via WindowInsetsController. */
- public boolean hideImeWithWindowInsetsController() {
- WindowInsetsController windowInsetsController = mEditText.getWindowInsetsController();
- windowInsetsController.hide(WindowInsets.Type.ime());
+ public void hideImeWithWindowInsetsController() {
+ final var controller = mEditText.getWindowInsetsController();
+ controller.hide(WindowInsets.Type.ime());
Log.i(TAG, "hideIme() via WindowInsetsController");
- return true;
}
}