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

Commit 69ab104a authored by Tarandeep Singh's avatar Tarandeep Singh
Browse files

Keep IME above starting window.

While app window is animating-in, IME window is child of aboveAppContainers.
If app requests IME on activity resume, IME will start animating-in
above Snapshot during app window animation.
However when app window animation finishes, IME's parent is no
longer aboveAppContainers, thereby making snapshot occlude
IME briefly. This results in flashing.

The fix is to keep IME in aboveAppContainers as long as startingWindow
is not removed from hierarchy.

Bug: 137534359
Test: Manual and atest ZOrderingTests AppWindowTokenTests
Change-Id: I78c939e8d1f23144162ba9eb8d834150fdd08ae8
parent eaadb371
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
    boolean removed;

    // Information about an application starting window if displayed.
    // Note: these are de-referenced before the starting window animates away.
    StartingData mStartingData;
    WindowState startingWindow;
    StartingSurface startingSurface;
@@ -1243,6 +1244,21 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
        return true;
    }

    /**
     * @return {@code true} if starting window is in app's hierarchy.
     */
    boolean hasStartingWindow() {
        if (startingDisplayed || mStartingData != null) {
            return true;
        }
        for (int i = mChildren.size() - 1; i >= 0; i--) {
            if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
                return true;
            }
        }
        return false;
    }

    @Override
    void addWindow(WindowState w) {
        super.addWindow(w);
+7 −3
Original line number Diff line number Diff line
@@ -4845,9 +4845,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        //
        // In the case where we have no IME target we assign it where it's base layer would
        // place it in the AboveAppWindowContainers.
        if (imeTarget != null && !(imeTarget.inSplitScreenWindowingMode()
                || imeTarget.mToken.isAppAnimating())
                && (imeTarget.getSurfaceControl() != null)) {
        //
        // Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
        // so it get's layered above the starting window.
        if (imeTarget != null
                && !(imeTarget.mAppToken != null && imeTarget.mAppToken.hasStartingWindow())
                && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
                && (imeTarget.getSurfaceControl() != null))) {
            mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
                    // TODO: We need to use an extra level on the app surface to ensure
                    // this is always above SurfaceView but always below attached window.
+15 −0
Original line number Diff line number Diff line
@@ -504,6 +504,21 @@ public class AppWindowTokenTests extends WindowTestsBase {
        assertEquals(stackBounds, mToken.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
    }

    @Test
    public void testHasStartingWindow() {
        final WindowManager.LayoutParams attrs =
                new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
        final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mToken);
        mToken.startingDisplayed = true;
        mToken.addWindow(startingWindow);
        assertTrue("Starting window should be present", mToken.hasStartingWindow());
        mToken.startingDisplayed = false;
        assertTrue("Starting window should be present", mToken.hasStartingWindow());

        mToken.removeChild(startingWindow);
        assertFalse("Starting window should not be present", mToken.hasStartingWindow());
    }

    private void assertHasStartingWindow(AppWindowToken atoken) {
        assertNotNull(atoken.startingSurface);
        assertNotNull(atoken.mStartingData);