Loading services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java +223 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package com.android.inputmethodservice; import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS; import static android.content.Intent.FLAG_RECEIVER_FOREGROUND; import static android.view.WindowInsets.Type.captionBar; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper.EVENT_CONFIG; import static com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper.EVENT_HIDE; Loading @@ -30,19 +33,32 @@ import static com.android.internal.inputmethod.InputMethodNavButtonFlags.SHOW_IM 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.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import android.app.ActivityManager; import android.app.Instrumentation; import android.app.KeyguardManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Insets; import android.os.Build; import android.os.RemoteException; import android.os.SystemClock; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.server.wm.DumpOnFailure; import android.server.wm.LockScreenSession; import android.server.wm.WindowManagerStateHelper; import android.util.Log; import android.view.View; Loading @@ -50,6 +66,7 @@ import android.view.WindowInsets; import android.view.WindowInsetsAnimation; import android.view.WindowManagerGlobal; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.Flags; import android.view.inputmethod.InputMethodManager; import androidx.annotation.NonNull; Loading @@ -58,6 +75,7 @@ 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.Direction; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.Until; Loading @@ -81,6 +99,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @RunWith(AndroidJUnit4.class) @MediumTest Loading @@ -102,6 +121,13 @@ public class InputMethodServiceTest { /** Timeout during which the event is not expected. */ private static final long NOT_EXCEPT_TIMEOUT_MS = 2000L * Build.HW_TIMEOUT_MULTIPLIER; /** Time to wait for UiAutomator scroll to finish. */ // TODO(b/371520375): Remove after UiAutomator scroll waits for animation to finish. private static final long SCROLL_TIMEOUT_MS = 500; /** Percentage to scroll by, to reach the top of a scrollable item. */ private static final float SCROLL_TOP_PERCENT = 100; /** Command to set showing the IME when a hardware keyboard is connected. */ private static final String SET_SHOW_IME_WITH_HARD_KEYBOARD_CMD = "settings put secure " + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD; Loading @@ -119,7 +145,8 @@ public class InputMethodServiceTest { private final GestureNavSwitchHelper mGestureNavSwitchHelper = new GestureNavSwitchHelper(); private final DeviceFlagsValueProvider mFlagsValueProvider = new DeviceFlagsValueProvider(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public final TestName mName = new TestName(); Loading Loading @@ -995,6 +1022,201 @@ public class InputMethodServiceTest { } } /** * Shows the Input Method Switcher menu and verifies opening the IME Language Settings activity * by tapping on the button, when the device is provisioned. */ @RequiresFlagsEnabled(Flags.FLAG_IME_SWITCHER_REVAMP) @Test public void testImeSwitcherMenu_openLanguageSettings() throws Exception { final var context = mInstrumentation.getTargetContext(); try (var ignored = withDeviceProvisioned(context, true /* provisioned */)) { showImeSwitcherMenu(false /* showWhenLocked */); final var info = mImm.getCurrentInputMethodInfo(); assertEquals(mInputMethodId, info != null ? info.getId() : null); final var container = mUiDevice.wait(Until.findObject(By.res("android:id/container")), TIMEOUT_MS); assertNotNull("Container view should be found.", container); // Make sure the container starts at the top. container.scroll(Direction.UP, SCROLL_TOP_PERCENT); final var languageSettingsButtonUiObject = container.scrollUntil(Direction.DOWN, Until.findObject(By.res("android:id/button1"))); assertNotNull("Language settings button should be found", languageSettingsButtonUiObject); // TODO(b/371520375): Remove after UiAutomator scroll waits for animation to finish. SystemClock.sleep(SCROLL_TIMEOUT_MS); // Tapping on the language settings button should dismiss the menu. languageSettingsButtonUiObject.click(); final var languageSettingsComponent = new ComponentName( "com.android.apps.inputmethod.simpleime", "com.android.apps.inputmethod.simpleime.LanguageSettingsActivity"); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(languageSettingsComponent) .and(WindowManagerStateHelper::activityWindowFocused), "Language settings activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should no longer be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); } } /** * Shows the Input Method Switcher menu and verifies the IME Language Settings button is not * visible when the screen is secure locked. */ @RequiresFlagsEnabled(Flags.FLAG_IME_SWITCHER_REVAMP) @Test public void testImeSwitcherMenu_noLanguageSettingsWhenScreenLocked() throws Exception { final var context = mInstrumentation.getTargetContext(); assumeFalse(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_AUTOMOTIVE)); assumeFalse(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK)); assumeTrue(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS)); try (var lockScreenSession = new LockScreenSession(mInstrumentation, mWmState); var ignored = withDeviceProvisioned(context, true /* provisioned */)) { lockScreenSession.setLockCredential().gotoKeyguard(); final var km = context.getSystemService(KeyguardManager.class); assertNotNull("KeyguardManager must be found", km); assertTrue("keyguard is locked", km.isKeyguardLocked()); assertTrue("keyguard is secure", km.isKeyguardSecure()); showImeSwitcherMenu(true /* showWhenLocked */); final var container = mUiDevice.wait(Until.findObject(By.res("android:id/container")), TIMEOUT_MS); assertNotNull("Container view should be found.", container); // Make sure the container starts at the top. container.scroll(Direction.UP, SCROLL_TOP_PERCENT); final boolean hasButton = container.scrollUntil(Direction.DOWN, Until.hasObject(By.res("android:id/button1"))); assertFalse("Language settings button should not be found", hasButton); context.sendBroadcast( new Intent(ACTION_CLOSE_SYSTEM_DIALOGS).setFlags(FLAG_RECEIVER_FOREGROUND)); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(WindowManagerStateHelper::activityWindowFocused), "Test activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should no longer be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); } } /** * Shows the Input Method Switcher menu and verifies the IME Language Settings button is not * visible when the device is not provisioned. */ @RequiresFlagsEnabled(Flags.FLAG_IME_SWITCHER_REVAMP) @Test public void testImeSwitcherMenu_noLanguageSettingsWhenDeviceNotProvisioned() throws Exception { final var context = mInstrumentation.getTargetContext(); assumeFalse(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_AUTOMOTIVE)); assumeTrue(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS)); try (var ignored = withDeviceProvisioned(context, false /* provisioned */)) { showImeSwitcherMenu(false /* showWhenLocked */); final var container = mUiDevice.wait(Until.findObject(By.res("android:id/container")), TIMEOUT_MS); assertNotNull("Container view should be found.", container); // Make sure the container starts at the top. container.scroll(Direction.UP, SCROLL_TOP_PERCENT); final boolean hasButton = container.scrollUntil(Direction.DOWN, Until.hasObject(By.res("android:id/button1"))); assertFalse("Language settings button should not be found", hasButton); context.sendBroadcast( new Intent(ACTION_CLOSE_SYSTEM_DIALOGS).setFlags(FLAG_RECEIVER_FOREGROUND)); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(WindowManagerStateHelper::activityWindowFocused), "Test activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should no longer be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); } } /** * Shows the IME Switcher menu on the test activity. * * @param showWhenLocked whether the test activity should be shown when the screen is locked. */ private void showImeSwitcherMenu(boolean showWhenLocked) { mActivity.setShowWhenLocked(showWhenLocked); // Make sure that the IME Switcher Menu is not shown in the initial state. mInstrumentation.getTargetContext().sendBroadcast(new Intent(ACTION_CLOSE_SYSTEM_DIALOGS) .setFlags(FLAG_RECEIVER_FOREGROUND)); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(WindowManagerStateHelper::activityWindowFocused), "Test activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should not be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); // Test InputMethodManager#showInputMethodPicker() works as expected. mImm.showInputMethodPicker(); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(Predicate.not(WindowManagerStateHelper::activityWindowFocused)) .and(state -> state.getMatchingWindows( ws -> ws.isSurfaceShown() && ws.getType() == TYPE_INPUT_METHOD_DIALOG) .findAny().isPresent()), "Input Method Dialog window should be focused on top of test activity"); assertWithMessage("Input Method Switcher Menu should be shown") .that(isInputMethodPickerShown(mImm)).isTrue(); } static void setDeviceProvisioned(@NonNull Context context, boolean provisioned) { Settings.Global.putInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, provisioned ? 1 : 0); } static boolean getDeviceProvisioned(@NonNull Context context) { try { return Settings.Global.getInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED) == 1; } catch (Settings.SettingNotFoundException e) { fail("Failed to get device provisioned state: " + e.getMessage()); return false; } } @NonNull static AutoCloseable withDeviceProvisioned(@NonNull Context context, boolean provisioned) { final boolean initial = getDeviceProvisioned(context); if (initial == provisioned) { return () -> {}; } setDeviceProvisioned(context, provisioned); assertWithMessage("New device provisioned state should be set") .that(getDeviceProvisioned(context)).isEqualTo(provisioned); return () -> { setDeviceProvisioned(context, initial); assertWithMessage("Initial device provisioned state should be restored") .that(getDeviceProvisioned(context)).isEqualTo(initial); }; } private void verifyInputViewStatus(@NonNull Runnable runnable, @Event int eventType, boolean eventExpected, boolean shown, @NonNull String message) { verifyInputViewStatusInternal(runnable, eventType, eventExpected, Loading services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml +10 −0 Original line number Diff line number Diff line Loading @@ -54,5 +54,15 @@ <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <activity android:name="com.android.apps.inputmethod.simpleime.SettingsActivity" android:label="Simple IME Settings" android:exported="true"> </activity> <activity android:name="com.android.apps.inputmethod.simpleime.LanguageSettingsActivity" android:label="Simple IME Language Settings" android:exported="true"> </activity> </application> </manifest> No newline at end of file services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/res/xml/method.xml +4 −2 Original line number Diff line number Diff line Loading @@ -15,7 +15,9 @@ ~ limitations under the License. --> <input-method xmlns:android="http://schemas.android.com/apk/res/android"> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.android.apps.inputmethod.simpleime.SettingsActivity" android:languageSettingsActivity="com.android.apps.inputmethod.simpleime.LanguageSettingsActivity"> <subtype android:label="SimpleIme" android:imeSubtypeLocale="en_US" Loading services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/LanguageSettingsActivity.java 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.apps.inputmethod.simpleime; import android.app.Activity; /** Stub activity to test out the language settings for Simple IME. */ public class LanguageSettingsActivity extends Activity { } services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SettingsActivity.java 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.apps.inputmethod.simpleime; import android.app.Activity; /** Stub activity to test out the settings for Simple IME. */ public class SettingsActivity extends Activity { } Loading
services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java +223 −1 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package com.android.inputmethodservice; import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS; import static android.content.Intent.FLAG_RECEIVER_FOREGROUND; import static android.view.WindowInsets.Type.captionBar; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper.EVENT_CONFIG; import static com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper.EVENT_HIDE; Loading @@ -30,19 +33,32 @@ import static com.android.internal.inputmethod.InputMethodNavButtonFlags.SHOW_IM 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.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import android.app.ActivityManager; import android.app.Instrumentation; import android.app.KeyguardManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Insets; import android.os.Build; import android.os.RemoteException; import android.os.SystemClock; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.server.wm.DumpOnFailure; import android.server.wm.LockScreenSession; import android.server.wm.WindowManagerStateHelper; import android.util.Log; import android.view.View; Loading @@ -50,6 +66,7 @@ import android.view.WindowInsets; import android.view.WindowInsetsAnimation; import android.view.WindowManagerGlobal; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.Flags; import android.view.inputmethod.InputMethodManager; import androidx.annotation.NonNull; Loading @@ -58,6 +75,7 @@ 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.Direction; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.Until; Loading @@ -81,6 +99,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; @RunWith(AndroidJUnit4.class) @MediumTest Loading @@ -102,6 +121,13 @@ public class InputMethodServiceTest { /** Timeout during which the event is not expected. */ private static final long NOT_EXCEPT_TIMEOUT_MS = 2000L * Build.HW_TIMEOUT_MULTIPLIER; /** Time to wait for UiAutomator scroll to finish. */ // TODO(b/371520375): Remove after UiAutomator scroll waits for animation to finish. private static final long SCROLL_TIMEOUT_MS = 500; /** Percentage to scroll by, to reach the top of a scrollable item. */ private static final float SCROLL_TOP_PERCENT = 100; /** Command to set showing the IME when a hardware keyboard is connected. */ private static final String SET_SHOW_IME_WITH_HARD_KEYBOARD_CMD = "settings put secure " + Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD; Loading @@ -119,7 +145,8 @@ public class InputMethodServiceTest { private final GestureNavSwitchHelper mGestureNavSwitchHelper = new GestureNavSwitchHelper(); private final DeviceFlagsValueProvider mFlagsValueProvider = new DeviceFlagsValueProvider(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Rule public final TestName mName = new TestName(); Loading Loading @@ -995,6 +1022,201 @@ public class InputMethodServiceTest { } } /** * Shows the Input Method Switcher menu and verifies opening the IME Language Settings activity * by tapping on the button, when the device is provisioned. */ @RequiresFlagsEnabled(Flags.FLAG_IME_SWITCHER_REVAMP) @Test public void testImeSwitcherMenu_openLanguageSettings() throws Exception { final var context = mInstrumentation.getTargetContext(); try (var ignored = withDeviceProvisioned(context, true /* provisioned */)) { showImeSwitcherMenu(false /* showWhenLocked */); final var info = mImm.getCurrentInputMethodInfo(); assertEquals(mInputMethodId, info != null ? info.getId() : null); final var container = mUiDevice.wait(Until.findObject(By.res("android:id/container")), TIMEOUT_MS); assertNotNull("Container view should be found.", container); // Make sure the container starts at the top. container.scroll(Direction.UP, SCROLL_TOP_PERCENT); final var languageSettingsButtonUiObject = container.scrollUntil(Direction.DOWN, Until.findObject(By.res("android:id/button1"))); assertNotNull("Language settings button should be found", languageSettingsButtonUiObject); // TODO(b/371520375): Remove after UiAutomator scroll waits for animation to finish. SystemClock.sleep(SCROLL_TIMEOUT_MS); // Tapping on the language settings button should dismiss the menu. languageSettingsButtonUiObject.click(); final var languageSettingsComponent = new ComponentName( "com.android.apps.inputmethod.simpleime", "com.android.apps.inputmethod.simpleime.LanguageSettingsActivity"); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(languageSettingsComponent) .and(WindowManagerStateHelper::activityWindowFocused), "Language settings activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should no longer be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); } } /** * Shows the Input Method Switcher menu and verifies the IME Language Settings button is not * visible when the screen is secure locked. */ @RequiresFlagsEnabled(Flags.FLAG_IME_SWITCHER_REVAMP) @Test public void testImeSwitcherMenu_noLanguageSettingsWhenScreenLocked() throws Exception { final var context = mInstrumentation.getTargetContext(); assumeFalse(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_AUTOMOTIVE)); assumeFalse(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK)); assumeTrue(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS)); try (var lockScreenSession = new LockScreenSession(mInstrumentation, mWmState); var ignored = withDeviceProvisioned(context, true /* provisioned */)) { lockScreenSession.setLockCredential().gotoKeyguard(); final var km = context.getSystemService(KeyguardManager.class); assertNotNull("KeyguardManager must be found", km); assertTrue("keyguard is locked", km.isKeyguardLocked()); assertTrue("keyguard is secure", km.isKeyguardSecure()); showImeSwitcherMenu(true /* showWhenLocked */); final var container = mUiDevice.wait(Until.findObject(By.res("android:id/container")), TIMEOUT_MS); assertNotNull("Container view should be found.", container); // Make sure the container starts at the top. container.scroll(Direction.UP, SCROLL_TOP_PERCENT); final boolean hasButton = container.scrollUntil(Direction.DOWN, Until.hasObject(By.res("android:id/button1"))); assertFalse("Language settings button should not be found", hasButton); context.sendBroadcast( new Intent(ACTION_CLOSE_SYSTEM_DIALOGS).setFlags(FLAG_RECEIVER_FOREGROUND)); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(WindowManagerStateHelper::activityWindowFocused), "Test activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should no longer be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); } } /** * Shows the Input Method Switcher menu and verifies the IME Language Settings button is not * visible when the device is not provisioned. */ @RequiresFlagsEnabled(Flags.FLAG_IME_SWITCHER_REVAMP) @Test public void testImeSwitcherMenu_noLanguageSettingsWhenDeviceNotProvisioned() throws Exception { final var context = mInstrumentation.getTargetContext(); assumeFalse(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_AUTOMOTIVE)); assumeTrue(context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS)); try (var ignored = withDeviceProvisioned(context, false /* provisioned */)) { showImeSwitcherMenu(false /* showWhenLocked */); final var container = mUiDevice.wait(Until.findObject(By.res("android:id/container")), TIMEOUT_MS); assertNotNull("Container view should be found.", container); // Make sure the container starts at the top. container.scroll(Direction.UP, SCROLL_TOP_PERCENT); final boolean hasButton = container.scrollUntil(Direction.DOWN, Until.hasObject(By.res("android:id/button1"))); assertFalse("Language settings button should not be found", hasButton); context.sendBroadcast( new Intent(ACTION_CLOSE_SYSTEM_DIALOGS).setFlags(FLAG_RECEIVER_FOREGROUND)); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(WindowManagerStateHelper::activityWindowFocused), "Test activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should no longer be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); } } /** * Shows the IME Switcher menu on the test activity. * * @param showWhenLocked whether the test activity should be shown when the screen is locked. */ private void showImeSwitcherMenu(boolean showWhenLocked) { mActivity.setShowWhenLocked(showWhenLocked); // Make sure that the IME Switcher Menu is not shown in the initial state. mInstrumentation.getTargetContext().sendBroadcast(new Intent(ACTION_CLOSE_SYSTEM_DIALOGS) .setFlags(FLAG_RECEIVER_FOREGROUND)); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(WindowManagerStateHelper::activityWindowFocused), "Test activity should have the focused window"); assertWithMessage("Input Method Switcher Menu should not be shown") .that(isInputMethodPickerShown(mImm)).isFalse(); // Test InputMethodManager#showInputMethodPicker() works as expected. mImm.showInputMethodPicker(); mWmState.waitAndAssert( WindowManagerStateHelper.focusedActivity(mActivity.getComponentName()) .and(Predicate.not(WindowManagerStateHelper::activityWindowFocused)) .and(state -> state.getMatchingWindows( ws -> ws.isSurfaceShown() && ws.getType() == TYPE_INPUT_METHOD_DIALOG) .findAny().isPresent()), "Input Method Dialog window should be focused on top of test activity"); assertWithMessage("Input Method Switcher Menu should be shown") .that(isInputMethodPickerShown(mImm)).isTrue(); } static void setDeviceProvisioned(@NonNull Context context, boolean provisioned) { Settings.Global.putInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, provisioned ? 1 : 0); } static boolean getDeviceProvisioned(@NonNull Context context) { try { return Settings.Global.getInt(context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED) == 1; } catch (Settings.SettingNotFoundException e) { fail("Failed to get device provisioned state: " + e.getMessage()); return false; } } @NonNull static AutoCloseable withDeviceProvisioned(@NonNull Context context, boolean provisioned) { final boolean initial = getDeviceProvisioned(context); if (initial == provisioned) { return () -> {}; } setDeviceProvisioned(context, provisioned); assertWithMessage("New device provisioned state should be set") .that(getDeviceProvisioned(context)).isEqualTo(provisioned); return () -> { setDeviceProvisioned(context, initial); assertWithMessage("Initial device provisioned state should be restored") .that(getDeviceProvisioned(context)).isEqualTo(initial); }; } private void verifyInputViewStatus(@NonNull Runnable runnable, @Event int eventType, boolean eventExpected, boolean shown, @NonNull String message) { verifyInputViewStatusInternal(runnable, eventType, eventExpected, Loading
services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/AndroidManifest.xml +10 −0 Original line number Diff line number Diff line Loading @@ -54,5 +54,15 @@ <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <activity android:name="com.android.apps.inputmethod.simpleime.SettingsActivity" android:label="Simple IME Settings" android:exported="true"> </activity> <activity android:name="com.android.apps.inputmethod.simpleime.LanguageSettingsActivity" android:label="Simple IME Language Settings" android:exported="true"> </activity> </application> </manifest> No newline at end of file
services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/res/xml/method.xml +4 −2 Original line number Diff line number Diff line Loading @@ -15,7 +15,9 @@ ~ limitations under the License. --> <input-method xmlns:android="http://schemas.android.com/apk/res/android"> <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.android.apps.inputmethod.simpleime.SettingsActivity" android:languageSettingsActivity="com.android.apps.inputmethod.simpleime.LanguageSettingsActivity"> <subtype android:label="SimpleIme" android:imeSubtypeLocale="en_US" Loading
services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/LanguageSettingsActivity.java 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.apps.inputmethod.simpleime; import android.app.Activity; /** Stub activity to test out the language settings for Simple IME. */ public class LanguageSettingsActivity extends Activity { }
services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/SettingsActivity.java 0 → 100644 +23 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.apps.inputmethod.simpleime; import android.app.Activity; /** Stub activity to test out the settings for Simple IME. */ public class SettingsActivity extends Activity { }