Loading tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java +109 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -96,7 +102,7 @@ public final class ConcurrentMultiUserTest { } @Test public void driverShowImeNotAffectPassenger() { public void driverShowImeNotAffectPassenger() throws Exception { assertDriverImeHidden(); assertPassengerImeHidden(); Loading @@ -104,6 +110,33 @@ public final class ConcurrentMultiUserTest { assertPassengerImeHidden(); } @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(); Loading Loading @@ -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(); Loading @@ -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. Loading tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java +76 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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); Loading @@ -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())); } } tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java +7 −3 Original line number Diff line number Diff line Loading @@ -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; } Loading
tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/ConcurrentMultiUserTest.java +109 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -96,7 +102,7 @@ public final class ConcurrentMultiUserTest { } @Test public void driverShowImeNotAffectPassenger() { public void driverShowImeNotAffectPassenger() throws Exception { assertDriverImeHidden(); assertPassengerImeHidden(); Loading @@ -104,6 +110,33 @@ public final class ConcurrentMultiUserTest { assertPassengerImeHidden(); } @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(); Loading Loading @@ -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(); Loading @@ -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. Loading
tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/MainActivity.java +76 −17 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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); Loading @@ -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())); } }
tests/inputmethod/ConcurrentMultiSessionImeTest/src/com/android/server/inputmethod/multisessiontest/TestRequestConstants.java +7 −3 Original line number Diff line number Diff line Loading @@ -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; }