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

Commit 5dbc3c62 authored by wilsonshih's avatar wilsonshih
Browse files

Always defer remove snapshot starting window if it contains IME

The ActivityRecord#mStartingData would already be removed when calling
to removeStartingWindow, so check StartingData#hasImeSurface is useless
Instead, we should pass that information when decideing to defer remove
snapshot starting window for IME.
Also since we are moving a task to front, should not check the
softInputMode attribute since the status may already changed from
previous launch.

Bug: 310467880
Test: launch app which softInputMode set to stateAlwaysHidden, invoke
IME window, move the task to back then move it to front.
Verify the snapshot starting window will wait for IME show signal.

Change-Id: If829016d5a1a486b3a424fc6add32ceb5d2e3f05
parent 0dbcde30
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -2565,7 +2565,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    }
                }
                if (abort) {
                    surface.remove(false /* prepareAnimation */);
                    surface.remove(false /* prepareAnimation */, false /* hasImeSurface */);
                }
            } else {
                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
@@ -2898,6 +2898,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        final StartingSurfaceController.StartingSurface surface;
        final boolean animate;
        final boolean hasImeSurface;
        if (mStartingData != null) {
            if (mStartingData.mWaitForSyncTransactionCommit
                    || mTransitionController.isCollecting(this)) {
@@ -2907,6 +2908,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            }
            animate = prepareAnimation && mStartingData.needRevealAnimation()
                    && mStartingWindow.isVisibleByPolicy();
            hasImeSurface = mStartingData.hasImeSurface();
            ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
                            + " animate=%b Callers=%s", this, mStartingWindow, animate,
                    Debug.getCallers(5));
@@ -2926,7 +2928,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    this);
            return;
        }
        surface.remove(animate);
        surface.remove(animate, hasImeSurface);
    }

    /**
+0 −24
Original line number Diff line number Diff line
@@ -69,8 +69,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
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_BOOT_PROGRESS;
@@ -1917,28 +1915,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        return true;
    }

    /** Returns {@code true} if the IME is possible to show on the launching activity. */
    boolean mayImeShowOnLaunchingActivity(@NonNull ActivityRecord r) {
        final WindowState win = r.findMainWindow(false /* exclude starting window */);
        if (win == null) {
            return false;
        }
        // See InputMethodManagerService#shouldRestoreImeVisibility that we expecting the IME
        // should be hidden when the window set the hidden softInputMode.
        final int softInputMode = win.mAttrs.softInputMode;
        switch (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
            case SOFT_INPUT_STATE_ALWAYS_HIDDEN:
            case SOFT_INPUT_STATE_HIDDEN:
                return false;
        }
        final boolean useIme = r.getWindow(
                w -> WindowManager.LayoutParams.mayUseInputMethod(w.mAttrs.flags)) != null;
        if (!useIme) {
            return false;
        }
        return r.mLastImeShown || (r.mStartingData != null && r.mStartingData.hasImeSurface());
    }

    /** Returns {@code true} if the top activity is transformed with the new rotation of display. */
    boolean hasTopFixedRotationLaunchingApp() {
        return mFixedRotationLaunchingApp != null
+4 −2
Original line number Diff line number Diff line
@@ -276,12 +276,14 @@ public class StartingSurfaceController {
        /**
         * Removes the starting window surface. Do not hold the window manager lock when calling
         * this method!
         *
         * @param animate Whether need to play the default exit animation for starting window.
         * @param hasImeSurface Whether the starting window has IME surface.
         */
        public void remove(boolean animate) {
        public void remove(boolean animate, boolean hasImeSurface) {
            synchronized (mService.mGlobalLock) {
                mService.mAtmService.mTaskOrganizerController.removeStartingWindow(mTask,
                        mTaskOrganizer, animate);
                        mTaskOrganizer, animate, hasImeSurface);
            }
        }
    }
+9 −8
Original line number Diff line number Diff line
@@ -673,7 +673,8 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
        return true;
    }

    void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation) {
    void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation,
            boolean hasImeSurface) {
        final Task rootTask = task.getRootTask();
        if (rootTask == null) {
            return;
@@ -693,13 +694,13 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
        if (topActivity != null) {
            // Set defer remove mode for IME
            final DisplayContent dc = topActivity.getDisplayContent();
            final WindowState imeWindow = dc.mInputMethodWindow;
            if (topActivity.isVisibleRequested() && imeWindow != null
                    && dc.mayImeShowOnLaunchingActivity(topActivity)
            if (hasImeSurface) {
                if (topActivity.isVisibleRequested() && dc.mInputMethodWindow != null
                        && dc.isFixedRotationLaunchingApp(topActivity)) {
                    removalInfo.deferRemoveForImeMode = DEFER_MODE_ROTATION;
            } else if (dc.mayImeShowOnLaunchingActivity(topActivity)) {
                } else {
                    removalInfo.deferRemoveForImeMode = DEFER_MODE_NORMAL;
                }
            } else {
                removalInfo.deferRemoveForImeMode = DEFER_MODE_NONE;
            }
+0 −22
Original line number Diff line number Diff line
@@ -51,8 +51,6 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
@@ -2762,26 +2760,6 @@ public class DisplayContentTests extends WindowTestsBase {
                mDisplayContent.getKeepClearAreas());
    }

    @Test
    public void testMayImeShowOnLaunchingActivity_negativeWhenSoftInputModeHidden() {
        final ActivityRecord app = createActivityRecord(mDisplayContent);
        final WindowState appWin = createWindow(null, TYPE_BASE_APPLICATION, app, "appWin");
        createWindow(null, TYPE_APPLICATION_STARTING, app, "startingWin");
        app.mStartingData = mock(SnapshotStartingData.class);
        // Assume the app has shown IME before and warm launching with a snapshot window.
        doReturn(true).when(app.mStartingData).hasImeSurface();

        // Expect true when this IME focusable activity will show IME during launching.
        assertTrue(WindowManager.LayoutParams.mayUseInputMethod(appWin.mAttrs.flags));
        assertTrue(mDisplayContent.mayImeShowOnLaunchingActivity(app));

        // Not expect IME will be shown during launching if the app's softInputMode is hidden.
        appWin.mAttrs.softInputMode = SOFT_INPUT_STATE_ALWAYS_HIDDEN;
        assertFalse(mDisplayContent.mayImeShowOnLaunchingActivity(app));
        appWin.mAttrs.softInputMode = SOFT_INPUT_STATE_HIDDEN;
        assertFalse(mDisplayContent.mayImeShowOnLaunchingActivity(app));
    }

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