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

Commit 01edb1b9 authored by Ming-Shin Lu's avatar Ming-Shin Lu Committed by Android (Google) Code Review
Browse files

Merge "Fix ANR when switching the app task but IME selection dialog focused"

parents 2d3e3569 bd868b66
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -116,8 +116,10 @@ public abstract class InputMethodManagerInternal {
     *
     * @param windowToken the window token that is now in control, or {@code null} if no client
     *                   window is in control of the IME.
     * @param imeParentChanged {@code true} when the window manager thoughts the IME surface parent
     *                         will end up to change later, or {@code false} otherwise.
     */
    public abstract void reportImeControl(@Nullable IBinder windowToken);
    public abstract void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged);

    /**
     * Destroys the IME surface.
@@ -176,7 +178,8 @@ public abstract class InputMethodManagerInternal {
                }

                @Override
                public void reportImeControl(@Nullable IBinder windowToken) {
                public void reportImeControl(@Nullable IBinder windowToken,
                        boolean imeParentChanged) {
                }

                @Override
+9 −3
Original line number Diff line number Diff line
@@ -4934,13 +4934,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        return mInputManagerInternal.transferTouchFocus(sourceInputToken, curHostInputToken);
    }

    private void reportImeControl(@Nullable IBinder windowToken) {
    private void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) {
        synchronized (mMethodMap) {
            if (mCurFocusedWindow != windowToken) {
                // mCurPerceptible was set by the focused window, but it is no longer in control,
                // so we reset mCurPerceptible.
                mCurPerceptible = true;
            }
            if (imeParentChanged) {
                // Hide the IME method menu earlier when the IME surface parent will change in
                // case seeing the dialog dismiss flickering during the next focused window
                // starting the input connection.
                mMenuController.hideInputMethodMenu();
            }
        }
    }

@@ -4998,8 +5004,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        }

        @Override
        public void reportImeControl(@Nullable IBinder windowToken) {
            mService.reportImeControl(windowToken);
        public void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) {
            mService.reportImeControl(windowToken, imeParentChanged);
        }

        @Override
+16 −7
Original line number Diff line number Diff line
@@ -733,14 +733,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp

        // When switching the app task, we keep the IME window visibility for better
        // transitioning experiences.
        // However, in case IME created a child window without dismissing during the task
        // switching to keep the window focus because IME window has higher window hierarchy,
        // we don't give it focus if the next IME layering target doesn't request IME visible.
        if (w.mIsImWindow && w.isChildWindow() && (mImeLayeringTarget == null
        // However, in case IME created a child window or the IME selection dialog without
        // dismissing during the task switching to keep the window focus because IME window has
        // higher window hierarchy, we don't give it focus if the next IME layering target
        // doesn't request IME visible.
        if (w.mIsImWindow && (mImeLayeringTarget == null
                || !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME))) {
            if (w.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
                return false;
            }

            if (w.isChildWindow()) {
                return false;
            }
        }

        final ActivityRecord activity = w.mActivityRecord;

        if (focusedApp == null) {
@@ -3993,7 +4000,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        // Update Ime parent when IME insets leash created or the new IME layering target might
        // updated from setImeLayeringTarget, which is the best time that default IME visibility
        // has been settled down after IME control target changed.
        if (prevImeControlTarget != mImeControlTarget || forceUpdateImeParent) {
        final boolean imeParentChanged =
                prevImeControlTarget != mImeControlTarget || forceUpdateImeParent;
        if (imeParentChanged) {
            updateImeParent();
        }

@@ -4001,7 +4010,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        final IBinder token = win != null ? win.mClient.asBinder() : null;
        // Note: not allowed to call into IMMS with the WM lock held, hence the post.
        mWmService.mH.post(() ->
                InputMethodManagerInternal.get().reportImeControl(token)
                InputMethodManagerInternal.get().reportImeControl(token, imeParentChanged)
        );
    }

+26 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
@@ -2204,6 +2205,31 @@ public class DisplayContentTests extends WindowTestsBase {
        assertNotEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeMenuDialogFocusWhenImeLayeringTargetChanges() {
        final WindowState imeMenuDialog =
                createWindow(mImeWindow, TYPE_INPUT_METHOD_DIALOG, "imeMenuDialog");
        makeWindowVisibleAndDrawn(imeMenuDialog, mImeWindow);
        assertTrue(imeMenuDialog.canReceiveKeys());
        mDisplayContent.setInputMethodWindowLocked(mImeWindow);

        // Verify imeMenuDialog can be focused window if the next IME target requests IME visible.
        final WindowState imeAppTarget =
                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
        mDisplayContent.setImeLayeringTarget(imeAppTarget);
        spyOn(imeAppTarget);
        doReturn(true).when(imeAppTarget).getRequestedVisibility(ITYPE_IME);
        assertEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());

        // Verify imeMenuDialog doesn't be focused window if the next IME target does not
        // request IME visible.
        final WindowState nextImeAppTarget =
                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "nextImeAppTarget");
        mDisplayContent.setImeLayeringTarget(nextImeAppTarget);
        assertNotEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());
    }

    private void removeRootTaskTests(Runnable runnable) {
        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
        final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,