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

Commit 3a116254 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve InsetsPolicy#adjustVisibilityForIme when switching apps" into sc-dev

parents e835dab9 566dae8f
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -655,6 +655,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    /** Whether the IME is showing when transitioning away from this activity. */
    boolean mLastImeShown;

    /**
     * When set to true, the IME insets will be frozen until the next app becomes IME input target.
     * @see InsetsPolicy#adjustVisibilityForIme
     */
    boolean mImeInsetsFrozenUntilStartInput;

    /**
     * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
     * to help AR know that the app is in the process of closing but hasn't yet started closing on
@@ -1363,6 +1369,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        if (newTask != null && isState(RESUMED)) {
            newTask.setResumedActivity(this, "onParentChanged");
            mImeInsetsFrozenUntilStartInput = false;
        }

        if (rootTask != null && rootTask.topRunningActivity() == this) {
@@ -4759,6 +4766,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    && imeInputTarget.getWindow().mActivityRecord == this
                    && mDisplayContent.mInputMethodWindow != null
                    && mDisplayContent.mInputMethodWindow.isVisible();
            mImeInsetsFrozenUntilStartInput = true;
        }

        final DisplayContent displayContent = getDisplayContent();
@@ -5877,6 +5885,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            // closing activity having to wait until idle timeout to be stopped or destroyed if the
            // next activity won't report idle (e.g. repeated view animation).
            mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded();

            // If the activity is visible, but no windows are eligible to start input, unfreeze
            // to avoid permanently frozen IME insets.
            if (mImeInsetsFrozenUntilStartInput && getWindow(
                    win -> WindowManager.LayoutParams.mayUseInputMethod(win.mAttrs.flags))
                    == null) {
                mImeInsetsFrozenUntilStartInput = false;
            }
        }
    }

@@ -7792,6 +7808,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    @Override
    void onResize() {
        // Reset freezing IME insets flag when the activity resized.
        mImeInsetsFrozenUntilStartInput = false;
        super.onResize();
    }

    /** Returns true if the configuration is compatible with this activity. */
    boolean isConfigurationCompatible(Configuration config) {
        final int orientation = getRequestedOrientation();
+3 −0
Original line number Diff line number Diff line
@@ -3971,6 +3971,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    void updateImeInputAndControlTarget(WindowState target) {
        if (mImeInputTarget != target) {
            ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
            if (target != null && target.mActivityRecord != null) {
                target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
            }
            setImeInputTarget(target);
            updateImeControlTarget();
        }
+31 −10
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ class InsetsPolicy {
    InsetsState getInsetsForWindow(WindowState target) {
        final InsetsState originalState = mStateController.getInsetsForWindow(target);
        final InsetsState state = adjustVisibilityForTransientTypes(originalState);
        return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
        return adjustVisibilityForIme(target, state, state == originalState);
    }

    /**
@@ -241,17 +241,38 @@ class InsetsPolicy {
        return state;
    }

    // Navigation bar insets is always visible to IME.
    private static InsetsState adjustVisibilityForIme(InsetsState originalState,
    private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState,
            boolean copyState) {
        if (w.mIsImWindow) {
            // Navigation bar insets is always visible to IME.
            final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
            if (originalNavSource != null && !originalNavSource.isVisible()) {
            final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
                final InsetsState state = copyState ? new InsetsState(originalState)
                        : originalState;
                final InsetsSource navSource = new InsetsSource(originalNavSource);
                navSource.setVisible(true);
                state.addSource(navSource);
                return state;
            }
        } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
            // During switching tasks with gestural navigation, if the IME is attached to
            // one app window on that time, even the next app window is behind the IME window,
            // conceptually the window should not receive the IME insets if the next window is
            // not eligible IME requester and ready to show IME on top of it.
            final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
            final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);

            if (shouldImeAttachedToApp && originalImeSource != null) {
                final boolean imeVisibility =
                        w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME);
                final InsetsState state = copyState ? new InsetsState(originalState)
                        : originalState;
                final InsetsSource imeSource = new InsetsSource(originalImeSource);
                imeSource.setVisible(imeVisibility);
                state.addSource(imeSource);
                return state;
            }
        }
        return originalState;
    }

+68 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import static android.os.Process.NOBODY_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -2816,6 +2817,73 @@ public class ActivityRecordTests extends WindowTestsBase {
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
    }

    @Test
    public void testImeInsetsFrozenFlag_resetWhenReparented() {
        final ActivityRecord activity = createActivityWithTask();
        final WindowState app = createWindow(null, TYPE_APPLICATION, activity, "app");
        final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
        final Task newTask = new TaskBuilder(mSupervisor).build();
        makeWindowVisible(app, imeWindow);
        mDisplayContent.mInputMethodWindow = imeWindow;
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);

        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
        app.mActivityRecord.commitVisibility(false, false);
        assertTrue(app.mActivityRecord.mLastImeShown);
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Expect IME insets frozen state will reset when the activity is reparent to the new task.
        activity.setState(RESUMED, "test");
        activity.reparent(newTask, 0 /* top */, "test");
        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenResized() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        makeWindowVisibleAndDrawn(app, mImeWindow);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);

        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
        app.mActivityRecord.commitVisibility(false, false);
        assertTrue(app.mActivityRecord.mLastImeShown);
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Expect IME insets frozen state will reset when the activity is reparent to the new task.
        app.mActivityRecord.onResize();
        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
        makeWindowVisibleAndDrawn(app, mImeWindow);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.setImeInputTarget(app);

        // Simulate app is closing and expect the last IME is shown and IME insets is frozen.
        app.mActivityRecord.commitVisibility(false, false);
        app.mActivityRecord.onWindowsGone();

        assertTrue(app.mActivityRecord.mLastImeShown);
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Expect IME insets frozen state will reset when the activity has no IME focusable window.
        app.mActivityRecord.forAllWindowsUnchecked(w -> {
            w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
            return true;
        }, true);

        app.mActivityRecord.commitVisibility(true, false);
        app.mActivityRecord.onWindowsVisible();

        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    private void assertHasStartingWindow(ActivityRecord atoken) {
        assertNotNull(atoken.mStartingSurface);
        assertNotNull(atoken.mStartingData);
+1 −0
Original line number Diff line number Diff line
@@ -258,6 +258,7 @@ public class SystemServicesTestRule implements TestRule {
        final ActivityManagerInternal amInternal = mAmService.mInternal;
        spyOn(amInternal);
        doNothing().when(amInternal).trimApplications();
        doNothing().when(amInternal).scheduleAppGcs();
        doNothing().when(amInternal).updateCpuStats();
        doNothing().when(amInternal).updateOomAdj();
        doNothing().when(amInternal).updateBatteryStats(any(), anyInt(), anyInt(), anyBoolean());
Loading