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

Commit fcced52e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

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

Merge "Fix ANR when switching the app task but IME selection dialog focused" into sc-dev am: 1181f3e9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15398716

Change-Id: I7e5ca09074ad67b25ea49e55be5721ccda6ad98b
parents 46f99bdb 1181f3e9
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
@@ -4937,13 +4937,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();
            }
        }
    }

@@ -5001,8 +5007,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
+2 −1
Original line number Diff line number Diff line
@@ -225,7 +225,8 @@ public final class MultiClientInputMethodManagerService {
                        }

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

                        @Override
+16 −7
Original line number Diff line number Diff line
@@ -729,14 +729,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) {
@@ -3978,7 +3985,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();
        }

@@ -3986,7 +3995,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;
@@ -2201,6 +2202,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,