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

Commit 161897ee authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Remove mImeInsetsFrozenUntilStartInput

Since shell transition enabled, postApplyAnimation(visible=false)
is only called when the activity is completed invisible, rather
than transition ready in legacy transition. So the flag no longer
affects the appearance on screen.

Also the invisible-request state should already have the effect
as frozen insets by setInsetsFrozen/isReadyToDispatchInsetsState.

Bug: 365884835
Flag: EXEMPT remove outdated code
Test: atest WindowStateTests
Test: Open IME on Play and Messages, use gesture navigation
      to switch the tasks. The IME on the apps won't disappear
      during transition.
Change-Id: I697e4c93e2bd12971fb2104ccfa8170268a380b0
parent 71378c18
Loading
Loading
Loading
Loading
+0 −21
Original line number Diff line number Diff line
@@ -761,13 +761,6 @@ final class ActivityRecord extends WindowToken {
    /** 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
     * @see ImeInsetsSourceProvider#updateClientVisibility
     */
    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
@@ -1173,8 +1166,6 @@ final class ActivityRecord extends WindowToken {
                pw.print(" launchMode="); pw.println(launchMode);
        pw.print(prefix); pw.print("mActivityType=");
                pw.println(activityTypeToString(getActivityType()));
        pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput=");
                pw.println(mImeInsetsFrozenUntilStartInput);
        if (requestedVrComponent != null) {
            pw.print(prefix);
            pw.print("requestedVrComponent=");
@@ -5876,10 +5867,6 @@ final class ActivityRecord extends WindowToken {
        }

        final DisplayContent displayContent = getDisplayContent();
        if (!visible) {
            mImeInsetsFrozenUntilStartInput = true;
        }

        if (!displayContent.mClosingApps.contains(this)
                && !displayContent.mOpeningApps.contains(this)
                && !fromTransition) {
@@ -6945,14 +6932,6 @@ final class ActivityRecord extends WindowToken {
            // 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;
            }
        }
    }

+0 −29
Original line number Diff line number Diff line
@@ -4660,35 +4660,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        }
    }

    /**
     * Callback from {@link ImeInsetsSourceProvider#updateClientVisibility} for the system to
     * judge whether or not to notify the IME insets provider to dispatch this reported IME client
     * visibility state to the app clients when needed.
     */
    boolean onImeInsetsClientVisibilityUpdate() {
        boolean[] changed = new boolean[1];

        // Unlike the IME layering target or the control target can be updated during the layout
        // change, the IME input target requires to be changed after gaining the input focus.
        // In case unfreezing IME insets state may too early during IME focus switching, we unfreeze
        // when activities going to be visible until the input target changed, or the
        // activity was the current input target that has to unfreeze after updating the IME
        // client visibility.
        final ActivityRecord inputTargetActivity =
                mImeInputTarget != null ? mImeInputTarget.getActivityRecord() : null;
        final boolean targetChanged = mImeInputTarget != mLastImeInputTarget;
        if (targetChanged || inputTargetActivity != null && inputTargetActivity.isVisibleRequested()
                && inputTargetActivity.mImeInsetsFrozenUntilStartInput) {
            forAllActivities(r -> {
                if (r.mImeInsetsFrozenUntilStartInput && r.isVisibleRequested()) {
                    r.mImeInsetsFrozenUntilStartInput = false;
                    changed[0] = true;
                }
            });
        }
        return changed[0];
    }

    void updateImeControlTarget() {
        updateImeControlTarget(false /* forceUpdateImeParent */);
    }
+0 −1
Original line number Diff line number Diff line
@@ -307,7 +307,6 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider {
                reportImeDrawnForOrganizerIfNeeded((InsetsControlTarget) caller);
            }
        }
        changed |= mDisplayContent.onImeInsetsClientVisibilityUpdate();
        if (Flags.refactorInsetsController()) {
            if (changed) {
                ImeTracker.forLogging().onProgress(statsToken,
+0 −16
Original line number Diff line number Diff line
@@ -387,22 +387,6 @@ class InsetsPolicy {
                state.addSource(navSource);
            }
            return state;
        } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
            // During switching tasks with gestural navigation, before the next IME input target
            // starts the input, we should adjust and freeze the last IME visibility of the window
            // in case delivering obsoleted IME insets state during transitioning.
            final InsetsSource originalImeSource = originalState.peekSource(ID_IME);

            if (originalImeSource != null) {
                final boolean imeVisibility = w.isRequestedVisible(Type.ime());
                final InsetsState state = copyState
                        ? new InsetsState(originalState)
                        : originalState;
                final InsetsSource imeSource = new InsetsSource(originalImeSource);
                imeSource.setVisible(imeVisibility);
                state.addSource(imeSource);
                return state;
            }
        } else if (w.mImeInsetsConsumed) {
            // Set the IME source (if there is one) to be invisible if it has been consumed.
            final InsetsSource originalImeSource = originalState.peekSource(ID_IME);
+0 −180
Original line number Diff line number Diff line
@@ -49,17 +49,13 @@ import static android.content.res.Configuration.UI_MODE_TYPE_DESK;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
import static android.os.Process.NOBODY_UID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.InsetsSource.ID_IME;
import static android.view.WindowInsets.Type.ime;
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;
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;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_PIP;
@@ -125,7 +121,6 @@ import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.DestroyActivityItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.WindowStateResizeItem;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.Intent;
@@ -149,8 +144,6 @@ import android.view.DisplayInfo;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner.Stub;
import android.view.IWindowManager;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
@@ -171,7 +164,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;

import java.util.ArrayList;
@@ -3370,178 +3362,6 @@ public class ActivityRecordTests extends WindowTestsBase {
        assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
    }

    @SetupWindows(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() {
        final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
        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.
        mDisplayContent.mOpeningApps.clear();
        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.forAllWindows(w -> {
            w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
            return true;
        }, true);

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

        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
    }

    @SetupWindows(addWindows = W_INPUT_METHOD)
    @Test
    public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
        final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();

        mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
                mImeWindow, null, null);
        mImeWindow.getControllableInsetProvider().setServerVisible(true);

        InsetsSource imeSource = new InsetsSource(ID_IME, ime());
        app.mAboveInsetsState.addSource(imeSource);
        mDisplayContent.setImeLayeringTarget(app);
        mDisplayContent.updateImeInputAndControlTarget(app);

        InsetsState state = app.getInsetsState();
        assertFalse(state.getOrCreateSource(imeSource.getId(), ime()).isVisible());
        assertTrue(state.getOrCreateSource(imeSource.getId(), ime()).getFrame().isEmpty());

        // Simulate app is closing and expect IME insets is frozen.
        mDisplayContent.mOpeningApps.clear();
        app.mActivityRecord.commitVisibility(false, false);
        app.mActivityRecord.onWindowsGone();
        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Simulate app re-start input or turning screen off/on then unlocked by un-secure
        // keyguard to back to the app, expect IME insets is not frozen
        app.mActivityRecord.commitVisibility(true, false);
        mDisplayContent.updateImeInputAndControlTarget(app);
        performSurfacePlacementAndWaitForWindowAnimator();

        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        imeSource.setVisible(true);
        imeSource.setFrame(new Rect(100, 400, 500, 500));
        app.mAboveInsetsState.addSource(imeSource);

        // Verify when IME is visible and the app can receive the right IME insets from policy.
        makeWindowVisibleAndDrawn(app, mImeWindow);
        state = app.getInsetsState();
        assertTrue(state.peekSource(ID_IME).isVisible());
        assertEquals(state.peekSource(ID_IME).getFrame(), imeSource.getFrame());
    }

    @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD })
    @Test
    public void testImeInsetsFrozenFlag_noDispatchVisibleInsetsWhenAppNotRequest()
            throws RemoteException {
        final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).build();
        final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build();

        mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer(
                mImeWindow, null, null);
        mImeWindow.getControllableInsetProvider().setServerVisible(true);

        // Simulate app2 is closing and let app1 is visible to be IME targets.
        makeWindowVisibleAndDrawn(app1, mImeWindow);
        mDisplayContent.setImeLayeringTarget(app1);
        mDisplayContent.updateImeInputAndControlTarget(app1);
        app2.mActivityRecord.commitVisibility(false, false);

        // app1 requests IME visible.
        app1.setRequestedVisibleTypes(ime(), ime());
        mDisplayContent.getInsetsStateController().onRequestedVisibleTypesChanged(app1,
                null /* statsToken */);

        // Verify app1's IME insets is visible and app2's IME insets frozen flag set.
        assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible());
        assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        // Simulate switching to app2 to make it visible to be IME targets.
        spyOn(app2);
        spyOn(app2.mClient);
        spyOn(app2.getProcess());
        ArgumentCaptor<InsetsState> insetsStateCaptor = ArgumentCaptor.forClass(InsetsState.class);
        doReturn(true).when(app2).isReadyToDispatchInsetsState();
        mDisplayContent.setImeLayeringTarget(app2);
        app2.mActivityRecord.commitVisibility(true, false);
        mDisplayContent.updateImeInputAndControlTarget(app2);
        performSurfacePlacementAndWaitForWindowAnimator();

        // Verify after unfreezing app2's IME insets state, we won't dispatch visible IME insets
        // to client if the app didn't request IME visible.
        assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput);

        verify(app2.getProcess(), atLeastOnce()).scheduleClientTransactionItem(
                isA(WindowStateResizeItem.class));
        assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
    }

    @Test
    public void testImeInsetsFrozenFlag_multiWindowActivities() {
        final WindowToken imeToken = createTestWindowToken(TYPE_INPUT_METHOD, mDisplayContent);
        final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).setWindowToken(
                imeToken).build();
        makeWindowVisibleAndDrawn(ime);

        // Create a split-screen root task with activity1 and activity 2.
        final Task task = new TaskBuilder(mSupervisor)
                .setCreateParentTask(true).setCreateActivity(true).build();
        task.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        final ActivityRecord activity1 = task.getTopNonFinishingActivity();
        activity1.getTask().setResumedActivity(activity1, "testApp1");

        final ActivityRecord activity2 = new TaskBuilder(mSupervisor)
                .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW)
                .setCreateActivity(true).build().getTopMostActivity();
        activity2.getTask().setResumedActivity(activity2, "testApp2");
        activity2.getTask().setParent(task.getRootTask());

        // Simulate activity1 and activity2 both have set mImeInsetsFrozenUntilStartInput when
        // invisible to user.
        activity1.mImeInsetsFrozenUntilStartInput = true;
        activity2.mImeInsetsFrozenUntilStartInput = true;

        final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).setWindowToken(
                activity1).build();
        final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowToken(
                activity2).build();
        makeWindowVisibleAndDrawn(app1, app2);

        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
        controller.getImeSourceProvider().setWindowContainer(
                ime, null, null);
        ime.getControllableInsetProvider().setServerVisible(true);

        // app1 starts input and expect IME insets for all activities in split-screen will be
        // frozen until the input started.
        mDisplayContent.setImeLayeringTarget(app1);
        mDisplayContent.updateImeInputAndControlTarget(app1);
        mDisplayContent.computeImeTarget(true /* updateImeTarget */);
        performSurfacePlacementAndWaitForWindowAnimator();

        assertEquals(app1, mDisplayContent.getImeInputTarget());
        assertFalse(activity1.mImeInsetsFrozenUntilStartInput);
        assertFalse(activity2.mImeInsetsFrozenUntilStartInput);

        app1.setRequestedVisibleTypes(ime());
        controller.onRequestedVisibleTypesChanged(app1, null /* statsToken */);

        // Expect all activities in split-screen will get IME insets visible state
        assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible());
        assertTrue(app2.getInsetsState().peekSource(ID_IME).isVisible());
    }

    @Test
    public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() {
        final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
Loading