Loading services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java +146 −96 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import android.app.Instrumentation; import android.content.Context; import android.content.res.Configuration; import android.graphics.Insets; import android.os.RemoteException; Loading @@ -42,7 +41,6 @@ import android.provider.Settings; import android.server.wm.WindowManagerStateHelper; import android.util.Log; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.Flags; import android.view.inputmethod.InputMethodManager; Loading @@ -59,6 +57,7 @@ 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.GestureNavSwitchHelper; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; Loading Loading @@ -90,6 +89,8 @@ public class InputMethodServiceTest { private final WindowManagerStateHelper mWmState = new WindowManagerStateHelper(); private final GestureNavSwitchHelper mGestureNavSwitchHelper = new GestureNavSwitchHelper(); private final DeviceFlagsValueProvider mFlagsValueProvider = new DeviceFlagsValueProvider(); @Rule Loading @@ -100,7 +101,6 @@ public class InputMethodServiceTest { private Instrumentation mInstrumentation; private UiDevice mUiDevice; private Context mContext; private InputMethodManager mImm; private String mTargetPackageName; private String mInputMethodId; Loading @@ -112,8 +112,7 @@ public class InputMethodServiceTest { public void setUp() throws Exception { mInstrumentation = InstrumentationRegistry.getInstrumentation(); mUiDevice = UiDevice.getInstance(mInstrumentation); mContext = mInstrumentation.getContext(); mImm = mContext.getSystemService(InputMethodManager.class); mImm = mInstrumentation.getContext().getSystemService(InputMethodManager.class); mTargetPackageName = mInstrumentation.getTargetContext().getPackageName(); mInputMethodId = getInputMethodId(); prepareIme(); Loading Loading @@ -872,72 +871,96 @@ public class InputMethodServiceTest { * Verifies that clicking on the IME navigation bar back button hides the IME. */ @Test public void testBackButtonClick() { public void testBackButtonClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); mActivity.showImeWithWindowInsetsController(); }, () -> mActivity.showImeWithWindowInsetsController(), true /* expected */, true /* inputViewStarted */); assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); final var backButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButtonUiObject.click(); final var backButton = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButton.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. // 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(); } } finally { restoreNav[0].close(); } } /** * Verifies that long clicking on the IME navigation bar back button hides the IME. */ @Test public void testBackButtonLongClick() { public void testBackButtonLongClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); mActivity.showImeWithWindowInsetsController(); }, () -> mActivity.showImeWithWindowInsetsController(), true /* expected */, true /* inputViewStarted */); assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); final var backButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButtonUiObject.longClick(); final var backButton = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButton.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. // 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(); } } finally { restoreNav[0].close(); } } /** Loading @@ -945,14 +968,26 @@ public class InputMethodServiceTest { * or switches the input method. */ @Test public void testImeSwitchButtonClick() { public void testImeSwitchButtonClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); Loading @@ -964,8 +999,8 @@ public class InputMethodServiceTest { final var initialInfo = mImm.getCurrentInputMethodInfo(); final var imeSwitchButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitchButtonUiObject.click(); final var imeSwitcherButton = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitcherButton.click(); mInstrumentation.waitForIdleSync(); final var newInfo = mImm.getCurrentInputMethodInfo(); Loading @@ -979,20 +1014,35 @@ public class InputMethodServiceTest { // Hide the IME Switcher Menu before finishing. mUiDevice.pressBack(); } finally { restoreNav[0].close(); } } /** * Verifies that long clicking on the IME switch button shows the Input Method Switcher Menu. */ @Test public void testImeSwitchButtonLongClick() { public void testImeSwitchButtonLongClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); Loading @@ -1002,8 +1052,8 @@ public class InputMethodServiceTest { true /* inputViewStarted */); assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); final var imeSwitchButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitchButtonUiObject.longClick(); final var imeSwitcherButton = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitcherButton.longClick(); mInstrumentation.waitForIdleSync(); assertWithMessage("Input Method Switcher Menu is shown") Loading @@ -1013,6 +1063,9 @@ public class InputMethodServiceTest { // Hide the IME Switcher Menu before finishing. mUiDevice.pressBack(); } finally { restoreNav[0].close(); } } private void verifyInputViewStatus(@NonNull Runnable runnable, boolean expected, Loading Loading @@ -1105,6 +1158,9 @@ public class InputMethodServiceTest { // Get the new TestActivity. mActivity = TestActivity.getLastCreatedInstance(); assertWithMessage("Re-created activity is not null").that(mActivity).isNotNull(); // Wait for the new EditText to be served by InputMethodManager. eventually(() -> assertWithMessage("Has an input connection to the re-created Activity") .that(mImm.hasActiveInputConnection(mActivity.getEditText())).isTrue()); } verifyInputViewStatusOnMainSync( Loading Loading @@ -1214,18 +1270,12 @@ public class InputMethodServiceTest { return uiObject; } /** 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; } /** Checks whether the device has a navigation bar on the IME's display. */ private boolean hasNavigationBar() { try { return WindowManagerGlobal.getWindowManagerService() .hasNavigationBar(mInputMethodService.getDisplayId()); .hasNavigationBar(mInputMethodService.getDisplayId()) && mGestureNavSwitchHelper.hasNavigationBar(); } catch (RemoteException e) { fail("Failed to check whether the device has a navigation bar: " + e.getMessage()); return false; Loading services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ <activity android:name="com.android.apps.inputmethod.simpleime.testing.TestActivity" android:exported="false" android:label="TestActivity" android:configChanges="assetsPaths" android:launchMode="singleInstance" android:excludeFromRecents="true" android:noHistory="true" Loading Loading
services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java +146 −96 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import android.app.Instrumentation; import android.content.Context; import android.content.res.Configuration; import android.graphics.Insets; import android.os.RemoteException; Loading @@ -42,7 +41,6 @@ import android.provider.Settings; import android.server.wm.WindowManagerStateHelper; import android.util.Log; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.Flags; import android.view.inputmethod.InputMethodManager; Loading @@ -59,6 +57,7 @@ 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.GestureNavSwitchHelper; import com.android.compatibility.common.util.SystemUtil; import org.junit.After; Loading Loading @@ -90,6 +89,8 @@ public class InputMethodServiceTest { private final WindowManagerStateHelper mWmState = new WindowManagerStateHelper(); private final GestureNavSwitchHelper mGestureNavSwitchHelper = new GestureNavSwitchHelper(); private final DeviceFlagsValueProvider mFlagsValueProvider = new DeviceFlagsValueProvider(); @Rule Loading @@ -100,7 +101,6 @@ public class InputMethodServiceTest { private Instrumentation mInstrumentation; private UiDevice mUiDevice; private Context mContext; private InputMethodManager mImm; private String mTargetPackageName; private String mInputMethodId; Loading @@ -112,8 +112,7 @@ public class InputMethodServiceTest { public void setUp() throws Exception { mInstrumentation = InstrumentationRegistry.getInstrumentation(); mUiDevice = UiDevice.getInstance(mInstrumentation); mContext = mInstrumentation.getContext(); mImm = mContext.getSystemService(InputMethodManager.class); mImm = mInstrumentation.getContext().getSystemService(InputMethodManager.class); mTargetPackageName = mInstrumentation.getTargetContext().getPackageName(); mInputMethodId = getInputMethodId(); prepareIme(); Loading Loading @@ -872,72 +871,96 @@ public class InputMethodServiceTest { * Verifies that clicking on the IME navigation bar back button hides the IME. */ @Test public void testBackButtonClick() { public void testBackButtonClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); mActivity.showImeWithWindowInsetsController(); }, () -> mActivity.showImeWithWindowInsetsController(), true /* expected */, true /* inputViewStarted */); assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); final var backButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButtonUiObject.click(); final var backButton = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButton.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. // 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(); } } finally { restoreNav[0].close(); } } /** * Verifies that long clicking on the IME navigation bar back button hides the IME. */ @Test public void testBackButtonLongClick() { public void testBackButtonLongClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); mActivity.showImeWithWindowInsetsController(); }, () -> mActivity.showImeWithWindowInsetsController(), true /* expected */, true /* inputViewStarted */); assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); final var backButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButtonUiObject.longClick(); final var backButton = getUiObject(By.res(INPUT_METHOD_NAV_BACK_ID)); backButton.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. // 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(); } } finally { restoreNav[0].close(); } } /** Loading @@ -945,14 +968,26 @@ public class InputMethodServiceTest { * or switches the input method. */ @Test public void testImeSwitchButtonClick() { public void testImeSwitchButtonClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); Loading @@ -964,8 +999,8 @@ public class InputMethodServiceTest { final var initialInfo = mImm.getCurrentInputMethodInfo(); final var imeSwitchButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitchButtonUiObject.click(); final var imeSwitcherButton = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitcherButton.click(); mInstrumentation.waitForIdleSync(); final var newInfo = mImm.getCurrentInputMethodInfo(); Loading @@ -979,20 +1014,35 @@ public class InputMethodServiceTest { // Hide the IME Switcher Menu before finishing. mUiDevice.pressBack(); } finally { restoreNav[0].close(); } } /** * Verifies that long clicking on the IME switch button shows the Input Method Switcher Menu. */ @Test public void testImeSwitchButtonLongClick() { public void testImeSwitchButtonLongClick() throws Exception { assumeTrue("Must have a navigation bar", hasNavigationBar()); assumeTrue("Must be in gesture navigation mode", isGestureNavEnabled()); waitUntilActivityReadyForInputInjection(mActivity); setShowImeWithHardKeyboard(true /* enabled */); final boolean isGestureMode = mGestureNavSwitchHelper.isGestureMode(); final var restoreNav = new AutoCloseable[]{() -> {}}; try { if (!isGestureMode) { // Wait for onConfigurationChanged when changing navigation modes. verifyInputViewStatus( () -> restoreNav[0] = mGestureNavSwitchHelper.withGestureNavigationMode(), true, /* expected */ false /* inputViewStarted */ ); } verifyInputViewStatusOnMainSync( () -> { setDrawsImeNavBarAndSwitcherButton(true /* enabled */); Loading @@ -1002,8 +1052,8 @@ public class InputMethodServiceTest { true /* inputViewStarted */); assertWithMessage("IME is shown").that(mInputMethodService.isInputViewShown()).isTrue(); final var imeSwitchButtonUiObject = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitchButtonUiObject.longClick(); final var imeSwitcherButton = getUiObject(By.res(INPUT_METHOD_NAV_IME_SWITCHER_ID)); imeSwitcherButton.longClick(); mInstrumentation.waitForIdleSync(); assertWithMessage("Input Method Switcher Menu is shown") Loading @@ -1013,6 +1063,9 @@ public class InputMethodServiceTest { // Hide the IME Switcher Menu before finishing. mUiDevice.pressBack(); } finally { restoreNav[0].close(); } } private void verifyInputViewStatus(@NonNull Runnable runnable, boolean expected, Loading Loading @@ -1105,6 +1158,9 @@ public class InputMethodServiceTest { // Get the new TestActivity. mActivity = TestActivity.getLastCreatedInstance(); assertWithMessage("Re-created activity is not null").that(mActivity).isNotNull(); // Wait for the new EditText to be served by InputMethodManager. eventually(() -> assertWithMessage("Has an input connection to the re-created Activity") .that(mImm.hasActiveInputConnection(mActivity.getEditText())).isTrue()); } verifyInputViewStatusOnMainSync( Loading Loading @@ -1214,18 +1270,12 @@ public class InputMethodServiceTest { return uiObject; } /** 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; } /** Checks whether the device has a navigation bar on the IME's display. */ private boolean hasNavigationBar() { try { return WindowManagerGlobal.getWindowManagerService() .hasNavigationBar(mInputMethodService.getDisplayId()); .hasNavigationBar(mInputMethodService.getDisplayId()) && mGestureNavSwitchHelper.hasNavigationBar(); } catch (RemoteException e) { fail("Failed to check whether the device has a navigation bar: " + e.getMessage()); return false; Loading
services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ <activity android:name="com.android.apps.inputmethod.simpleime.testing.TestActivity" android:exported="false" android:label="TestActivity" android:configChanges="assetsPaths" android:launchMode="singleInstance" android:excludeFromRecents="true" android:noHistory="true" Loading