Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1057c67c authored by Yabin Huang's avatar Yabin Huang Committed by Android (Google) Code Review
Browse files

Merge "Add more ConcurrentMultiUserTest" into main

parents 93b2232c 2b60234a
Loading
Loading
Loading
Loading
+109 −5
Original line number Diff line number Diff line
@@ -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();

@@ -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();
@@ -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.
+76 −17
Original line number Diff line number Diff line
@@ -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()));
    }
}
+7 −3
Original line number Diff line number Diff line
@@ -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;
}