diff options
author | 2024-07-02 15:03:05 -0700 | |
---|---|---|
committer | 2024-07-09 16:52:31 -0700 | |
commit | 2b60234ad1ca27bb34353955f6584e47b318bee9 (patch) | |
tree | cf4f4912aa58e7a067ea3a8b87e1464c97b0f171 | |
parent | 177af6b61a94ee76fc8c5a059d592c2eda2af96e (diff) |
Add more ConcurrentMultiUserTest
Bug: 350562427
Test: atest com.android.server.inputmethod.multisessiontest.ConcurrentMultiUserTest
Flag: TEST_ONLY
Change-Id: I056b49a4454233762348d7567e0918eeae7b3c0f
3 files changed, 192 insertions, 25 deletions
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java index 0db0d954d14d..df2374572296 100644 --- a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java +++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java @@ -23,10 +23,15 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.getResponderUserId; import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.launchActivityAsUserSync; import static com.android.compatibility.common.util.concurrentuser.ConcurrentUserActivityUtils.sendBundleAndWaitForReply; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_DISPLAY_ID; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_EDITTEXT_CENTER; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_IME_SHOWN; import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_REQUEST_CODE; -import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_RESULT_CODE; -import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_HIDDEN; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_DISPLAY_ID; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_EDITTEXT_POSITION; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_HIDE_IME; import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_IME_STATUS; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_SHOW_IME; import static com.google.common.truth.Truth.assertWithMessage; @@ -66,6 +71,7 @@ public final class ConcurrentMultiUserTest { private static final ComponentName TEST_ACTIVITY = new ComponentName( getInstrumentation().getTargetContext().getPackageName(), MainActivity.class.getName()); + private static final long WAIT_TIME_MS = 3000L; private final Context mContext = getInstrumentation().getTargetContext(); private final InputMethodManager mInputMethodManager = mContext.getSystemService(InputMethodManager.class); @@ -96,7 +102,7 @@ public final class ConcurrentMultiUserTest { } @Test - public void driverShowImeNotAffectPassenger() { + public void driverShowImeNotAffectPassenger() throws Exception { assertDriverImeHidden(); assertPassengerImeHidden(); @@ -105,6 +111,33 @@ public final class ConcurrentMultiUserTest { } @Test + public void passengerShowImeNotAffectDriver() throws Exception { + assertDriverImeHidden(); + assertPassengerImeHidden(); + + showPassengerImeAndAssert(); + assertDriverImeHidden(); + } + + @Test + public void driverHideImeNotAffectPassenger() throws Exception { + showDriverImeAndAssert(); + showPassengerImeAndAssert(); + + hideDriverImeAndAssert(); + assertPassengerImeShown(); + } + + @Test + public void passengerHideImeNotAffectDriver() throws Exception { + showDriverImeAndAssert(); + showPassengerImeAndAssert(); + + hidePassengerImeAndAssert(); + assertDriverImeShown(); + } + + @Test public void imeListNotEmpty() { List<InputMethodInfo> driverImeList = mInputMethodManager.getInputMethodList(); assertWithMessage("Driver IME list shouldn't be empty") @@ -156,6 +189,11 @@ public final class ConcurrentMultiUserTest { setImeForUser(passenger, driver); } + private void assertDriverImeShown() { + assertWithMessage("Driver IME should be shown") + .that(mActivity.isMyImeVisible()).isTrue(); + } + private void assertDriverImeHidden() { assertWithMessage("Driver IME should be hidden") .that(mActivity.isMyImeVisible()).isFalse(); @@ -167,13 +205,79 @@ public final class ConcurrentMultiUserTest { Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(), mPeerUserId, bundleToSend); assertWithMessage("Passenger IME should be hidden") - .that(receivedBundle.getInt(KEY_RESULT_CODE)).isEqualTo(REPLY_IME_HIDDEN); + .that(receivedBundle.getBoolean(KEY_IME_SHOWN, /* defaultValue= */ true)).isFalse(); + } + + private void assertPassengerImeShown() { + final Bundle bundleToSend = new Bundle(); + bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_IME_STATUS); + Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(), + mPeerUserId, bundleToSend); + assertWithMessage("Passenger IME should be shown") + .that(receivedBundle.getBoolean(KEY_IME_SHOWN)).isTrue(); } - private void showDriverImeAndAssert() { + private void showDriverImeAndAssert() throws Exception { + // WindowManagerInternal only allows the top focused display to show IME, so this method + // taps the driver display in case it is not the top focused display. + moveDriverDisplayToTop(); + mActivity.showMyImeAndWait(); } + private void hideDriverImeAndAssert() { + mActivity.hideMyImeAndWait(); + } + + private void showPassengerImeAndAssert() throws Exception { + // WindowManagerInternal only allows the top focused display to show IME, so this method + // taps the passenger display in case it is not the top focused display. + movePassengerDisplayToTop(); + + Bundle bundleToSend = new Bundle(); + bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_SHOW_IME); + Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(), + mPeerUserId, bundleToSend); + + assertWithMessage("Passenger IME should be shown") + .that(receivedBundle.getBoolean(KEY_IME_SHOWN)).isTrue(); + } + + private void hidePassengerImeAndAssert() { + Bundle bundleToSend = new Bundle(); + bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_HIDE_IME); + Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(), + mPeerUserId, bundleToSend); + + assertWithMessage("Passenger IME should be hidden") + .that(receivedBundle.getBoolean(KEY_IME_SHOWN, /* defaultValue= */ true)).isFalse(); + } + + private void moveDriverDisplayToTop() throws Exception { + float[] driverEditTextCenter = mActivity.getEditTextCenter(); + SystemUtil.runShellCommand(mUiAutomation, String.format("input tap %f %f", + driverEditTextCenter[0], driverEditTextCenter[1])); + // TODO(b/350562427): get rid of Thread.sleep(). + Thread.sleep(WAIT_TIME_MS); + } + + private void movePassengerDisplayToTop() throws Exception { + final Bundle bundleToSend = new Bundle(); + bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_EDITTEXT_POSITION); + Bundle receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(), + mPeerUserId, bundleToSend); + final float[] passengerEditTextCenter = receivedBundle.getFloatArray(KEY_EDITTEXT_CENTER); + + bundleToSend.putInt(KEY_REQUEST_CODE, REQUEST_DISPLAY_ID); + receivedBundle = sendBundleAndWaitForReply(TEST_ACTIVITY.getPackageName(), + mPeerUserId, bundleToSend); + final int passengerDisplayId = receivedBundle.getInt(KEY_DISPLAY_ID); + SystemUtil.runShellCommand(mUiAutomation, String.format("input -d %d tap %f %f", + passengerDisplayId, passengerEditTextCenter[0], passengerEditTextCenter[1])); + // TODO(b/350562427): get rid of Thread.sleep(). + Thread.sleep(WAIT_TIME_MS); + } + /** * Disables/enables IME for {@code user1}, then verifies that the IME settings for {@code user1} * has changed as expected and {@code user2} stays the same. diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java index 3c97b79b83c1..fa0aa19a8822 100644 --- a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java +++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java @@ -16,20 +16,25 @@ package com.android.server.inputmethod.multisessiontest; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_DISPLAY_ID; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_EDITTEXT_CENTER; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_IME_SHOWN; import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_REQUEST_CODE; -import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.KEY_RESULT_CODE; -import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_HIDDEN; -import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REPLY_IME_SHOWN; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_DISPLAY_ID; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_EDITTEXT_POSITION; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_HIDE_IME; import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_IME_STATUS; +import static com.android.server.inputmethod.multisessiontest.TestRequestConstants.REQUEST_SHOW_IME; import android.app.Activity; import android.os.Bundle; import android.os.Process; import android.util.Log; -import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import androidx.annotation.WorkerThread; import androidx.core.view.ViewCompat; +import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; import com.android.compatibility.common.util.PollingCheck; @@ -43,7 +48,6 @@ public final class MainActivity extends ConcurrentUserActivityBase { private static final long WAIT_IME_TIMEOUT_MS = 3000; private EditText mEditor; - private InputMethodManager mImm; @Override protected void onCreate(Bundle savedInstanceState) { @@ -52,19 +56,56 @@ public final class MainActivity extends ConcurrentUserActivityBase { + Process.myUserHandle().getIdentifier() + " on display " + getDisplay().getDisplayId()); setContentView(R.layout.main_activity); - mImm = getSystemService(InputMethodManager.class); mEditor = requireViewById(R.id.edit_text); } @Override + protected void onResume() { + super.onResume(); + Log.v(TAG, "onResume"); + } + + @Override + protected void onPause() { + super.onPause(); + Log.v(TAG, "onPause"); + } + + @Override + protected void onStop() { + super.onStop(); + Log.v(TAG, "onResume"); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + Log.v(TAG, "onWindowFocusChanged " + hasFocus); + } + + @Override + @WorkerThread protected Bundle onBundleReceived(Bundle receivedBundle) { final int requestCode = receivedBundle.getInt(KEY_REQUEST_CODE); Log.v(TAG, "onBundleReceived() with request code:" + requestCode); final Bundle replyBundle = new Bundle(); switch (requestCode) { case REQUEST_IME_STATUS: - replyBundle.putInt(KEY_RESULT_CODE, - isMyImeVisible() ? REPLY_IME_SHOWN : REPLY_IME_HIDDEN); + replyBundle.putBoolean(KEY_IME_SHOWN, isMyImeVisible()); + break; + case REQUEST_SHOW_IME: + showMyImeAndWait(); + replyBundle.putBoolean(KEY_IME_SHOWN, isMyImeVisible()); + break; + case REQUEST_HIDE_IME: + hideMyImeAndWait(); + replyBundle.putBoolean(KEY_IME_SHOWN, isMyImeVisible()); + break; + case REQUEST_EDITTEXT_POSITION: + replyBundle.putFloatArray(KEY_EDITTEXT_CENTER, getEditTextCenter()); + break; + case REQUEST_DISPLAY_ID: + replyBundle.putInt(KEY_DISPLAY_ID, getDisplay().getDisplayId()); break; default: throw new RuntimeException("Received undefined request code:" + requestCode); @@ -77,23 +118,41 @@ public final class MainActivity extends ConcurrentUserActivityBase { return insets == null ? false : insets.isVisible(WindowInsetsCompat.Type.ime()); } + float[] getEditTextCenter() { + final float editTextCenterX = mEditor.getX() + 0.5f * mEditor.getWidth(); + final float editTextCenterY = mEditor.getY() + 0.5f * mEditor.getHeight(); + return new float[]{editTextCenterX, editTextCenterY}; + } + + @WorkerThread void showMyImeAndWait() { - Log.v(TAG, "showSoftInput"); runOnUiThread(() -> { - // requestFocus() must run on UI thread. + // View#requestFocus() and WindowInsetsControllerCompat#show() must run on UI thread. if (!mEditor.requestFocus()) { Log.e(TAG, "Failed to focus on mEditor"); return; } - if (!mImm.showSoftInput(mEditor, /* flags= */ 0)) { - Log.e(TAG, String.format("Failed to show my IME as user %d, " - + "mEditor:focused=%b,hasWindowFocus=%b", - Process.myUserHandle().getIdentifier(), - mEditor.isFocused(), mEditor.hasWindowFocus())); - } + // Compared to mImm.showSoftInput(), the call below is the recommended way to show the + // keyboard because it is guaranteed to be scheduled after the window is focused. + Log.v(TAG, "showSoftInput"); + WindowCompat.getInsetsController(getWindow(), mEditor).show( + WindowInsetsCompat.Type.ime()); }); PollingCheck.waitFor(WAIT_IME_TIMEOUT_MS, () -> isMyImeVisible(), - String.format("My IME (user %d) didn't show up", + String.format("%s: My IME (user %d) didn't show up", TAG, + Process.myUserHandle().getIdentifier())); + } + + @WorkerThread + void hideMyImeAndWait() { + runOnUiThread(() -> { + Log.v(TAG, "hideSoftInput"); + // WindowInsetsControllerCompat#hide() must run on UI thread. + WindowCompat.getInsetsController(getWindow(), mEditor) + .hide(WindowInsetsCompat.Type.ime()); + }); + PollingCheck.waitFor(WAIT_IME_TIMEOUT_MS, () -> !isMyImeVisible(), + String.format("%s: My IME (user %d) is still shown", TAG, Process.myUserHandle().getIdentifier())); } } diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java index 1501bfb69c92..68c9d5403c0b 100644 --- a/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java +++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java @@ -21,9 +21,13 @@ final class TestRequestConstants { } public static final String KEY_REQUEST_CODE = "key_request_code"; - public static final String KEY_RESULT_CODE = "key_result_code"; + public static final String KEY_EDITTEXT_CENTER = "key_edittext_center"; + public static final String KEY_DISPLAY_ID = "key_display_id"; + public static final String KEY_IME_SHOWN = "key_ime_shown"; public static final int REQUEST_IME_STATUS = 1; - public static final int REPLY_IME_SHOWN = 2; - public static final int REPLY_IME_HIDDEN = 3; + public static final int REQUEST_SHOW_IME = 2; + public static final int REQUEST_HIDE_IME = 3; + public static final int REQUEST_EDITTEXT_POSITION = 4; + public static final int REQUEST_DISPLAY_ID = 5; } |