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

Commit 7844ca2d authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Android (Google) Code Review
Browse files

Merge "Only give DisplayInsetsController control over IME in split-screen" into rvc-dev

parents 176c70ef cc57cb7e
Loading
Loading
Loading
Loading
+24 −33
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -141,6 +142,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.WindowConfiguration;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
@@ -3370,34 +3372,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
    }

    private boolean isImeControlledByApp() {
        return mInputMethodTarget != null && !WindowConfiguration.isSplitScreenWindowingMode(
                mInputMethodTarget.getWindowingMode());
    }

    boolean isImeAttachedToApp() {
        return (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord != null
        return isImeControlledByApp()
                && mInputMethodTarget.mActivityRecord != null
                && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
                // An activity with override bounds should be letterboxed inside its parent bounds,
                // so it doesn't fill the screen.
                && mInputMethodTarget.mActivityRecord.matchParentBounds());
    }

    /**
     * Get IME target that should host IME when this display that is reparented to another
     * WindowState.
     * IME is never displayed in a child display.
     * Use {@link WindowState#getImeControlTarget()} when IME target window
     * which originally called
     * {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is known.
     *
     * @return {@link WindowState} of host that controls IME.
     *         {@code null} when {@param dc} is not a virtual display.
     * @see DisplayContent#reparent
     */
    @Nullable
    WindowState getImeControlTarget() {
        WindowState imeTarget = mInputMethodTarget;
        if (imeTarget != null) {
            return imeTarget.getImeControlTarget();
        }

        return getInsetsStateController().getImeSourceProvider().getControlTarget().getWindow();
                && mInputMethodTarget.mActivityRecord.matchParentBounds();
    }

    /**
@@ -3407,7 +3393,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     *
     * @param target current IME target.
     * @return {@link WindowState} that can host IME.
     * @see DisplayContent#getImeControlTarget()
     */
    WindowState getImeHostOrFallback(WindowState target) {
        if (target != null && target.getDisplayContent().canShowIme()) {
@@ -3448,8 +3433,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    /**
     * The IME input target is the window which receives input from IME. It is also a candidate
     * which controls the visibility and animation of the input method window.
     *
     * @param target the window that receives input from IME.
     */
    void setInputMethodInputTarget(WindowState target) {
        if (mInputMethodInputTarget != target) {
@@ -3459,12 +3442,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    }

    private void updateImeControlTarget() {
        if (!isImeAttachedToApp() && mRemoteInsetsControlTarget != null) {
            mInputMethodControlTarget = mRemoteInsetsControlTarget;
        } else {
            // Otherwise, we just use the ime input target
            mInputMethodControlTarget = mInputMethodInputTarget;
        }
        mInputMethodControlTarget = computeImeControlTarget();
        mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
    }

@@ -3476,6 +3454,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
    }

    /**
     * Computes the window where we hand IME control to.
     */
    @VisibleForTesting
    InsetsControlTarget computeImeControlTarget() {
        if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null) {
            return mRemoteInsetsControlTarget;
        } else {
            // Otherwise, we just use the ime target as received from IME.
            return mInputMethodInputTarget;
        }
    }

    /**
     * Computes the window the IME should be attached to.
     */
+68 −21
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
@@ -84,10 +85,13 @@ import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowRotationCallback;
import android.view.IDisplayWindowRotationController;
import android.view.ISystemGestureExclusionListener;
import android.view.IWindowManager;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceControl.Transaction;
@@ -810,26 +814,20 @@ public class DisplayContentTests extends WindowTestsBase {

    @Test
    public void testComputeImeParent_app() throws Exception {
        try (final InsetsModeSession session =
                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
        final DisplayContent dc = createNewDisplay();
        dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
        assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(),
                dc.computeImeParent());
    }
    }

    @Test
    public void testComputeImeParent_app_notFullscreen() throws Exception {
        try (final InsetsModeSession session =
                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
        final DisplayContent dc = createNewDisplay();
        dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
        dc.mInputMethodTarget.setWindowingMode(
                WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
    }
    }

    @Test
    public void testComputeImeParent_app_notMatchParentBounds() {
@@ -843,12 +841,61 @@ public class DisplayContentTests extends WindowTestsBase {

    @Test
    public void testComputeImeParent_noApp() throws Exception {
        try (final InsetsModeSession session =
                     new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
        final DisplayContent dc = createNewDisplay();
        dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
        assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
    }

    @Test
    public void testComputeImeControlTarget() throws Exception {
        final DisplayContent dc = createNewDisplay();
        dc.setRemoteInsetsController(createDisplayWindowInsetsController());
        dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
        dc.mInputMethodTarget = dc.mInputMethodInputTarget;
        assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
    }

    @Test
    public void testComputeImeControlTarget_splitscreen() throws Exception {
        final DisplayContent dc = createNewDisplay();
        dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
        dc.mInputMethodInputTarget.setWindowingMode(
                WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        dc.mInputMethodTarget = dc.mInputMethodInputTarget;
        dc.setRemoteInsetsController(createDisplayWindowInsetsController());
        assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget());
    }

    @Test
    public void testComputeImeControlTarget_notMatchParentBounds() throws Exception {
        spyOn(mAppWindow.mActivityRecord);
        doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds();
        mDisplayContent.mInputMethodInputTarget = mAppWindow;
        mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget;
        mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
        assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget());
    }

    private IDisplayWindowInsetsController createDisplayWindowInsetsController() {
        return new IDisplayWindowInsetsController.Stub() {

            @Override
            public void insetsChanged(InsetsState insetsState) throws RemoteException {
            }

            @Override
            public void insetsControlChanged(InsetsState insetsState,
                    InsetsSourceControl[] insetsSourceControls) throws RemoteException {
            }

            @Override
            public void showInsets(int i, boolean b) throws RemoteException {
            }

            @Override
            public void hideInsets(int i, boolean b) throws RemoteException {
            }
        };
    }

    @Test