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

Commit 07cb272a authored by wilsonshih's avatar wilsonshih
Browse files

Surface should not be created for WindowContext initially.

Client may create a WindowContext, but without adding a window using
the corresponding WindowToken, initially creating a surface for the
token is very wasteful.
To avoid this, we should only create surfaces when the client is
needed.

Bug: 150813033
Test: atest WindowTokenTests
Test: No system crash when running FocusHandlingTest.
Change-Id: I0def6a436ad9d60948bfb029b3a7b6b44466d068
parent bfdf19c4
Loading
Loading
Loading
Loading
+8 −4
Original line number Original line Diff line number Diff line
@@ -378,10 +378,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        if (mSurfaceControl == null) {
        if (mSurfaceControl == null) {
            // If we don't yet have a surface, but we now have a parent, we should
            // If we don't yet have a surface, but we now have a parent, we should
            // build a surface.
            // build a surface.
            setSurfaceControl(makeSurface().build());
            createSurfaceControl(false /*force*/);
            getPendingTransaction().show(mSurfaceControl);
            onSurfaceShown(getPendingTransaction());
            updateSurfacePosition();
        } else {
        } else {
            // If we have a surface but a new parent, we just need to perform a reparent. Go through
            // If we have a surface but a new parent, we just need to perform a reparent. Go through
            // surface animator such that hierarchy is preserved when animating, i.e.
            // surface animator such that hierarchy is preserved when animating, i.e.
@@ -399,6 +396,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        scheduleAnimation();
        scheduleAnimation();
    }
    }


    void createSurfaceControl(boolean force) {
        setSurfaceControl(makeSurface().build());
        getPendingTransaction().show(mSurfaceControl);
        onSurfaceShown(getPendingTransaction());
        updateSurfacePosition();
    }

    /**
    /**
     * Called when the surface is shown for the first time.
     * Called when the surface is shown for the first time.
     */
     */
+15 −0
Original line number Original line Diff line number Diff line
@@ -100,6 +100,9 @@ class WindowToken extends WindowContainer<WindowState> {
    private Configuration mLastReportedConfig;
    private Configuration mLastReportedConfig;
    private int mLastReportedDisplay = INVALID_DISPLAY;
    private int mLastReportedDisplay = INVALID_DISPLAY;


    /**
     * When set to {@code true}, this window token is created from {@link android.app.WindowContext}
     */
    @VisibleForTesting
    @VisibleForTesting
    final boolean mFromClientToken;
    final boolean mFromClientToken;


@@ -278,6 +281,11 @@ class WindowToken extends WindowContainer<WindowState> {
            // Child windows are added to their parent windows.
            // Child windows are added to their parent windows.
            return;
            return;
        }
        }
        // This token is created from WindowContext and the client requests to addView now, create a
        // surface for this token.
        if (mSurfaceControl == null) {
            createSurfaceControl(true /* force */);
        }
        if (!mChildren.contains(win)) {
        if (!mChildren.contains(win)) {
            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
            addChild(win, mWindowComparator);
            addChild(win, mWindowComparator);
@@ -286,6 +294,13 @@ class WindowToken extends WindowContainer<WindowState> {
        }
        }
    }
    }


    @Override
    void createSurfaceControl(boolean force) {
        if (!mFromClientToken || force) {
            super.createSurfaceControl(force);
        }
    }

    /** Returns true if the token windows list is empty. */
    /** Returns true if the token windows list is empty. */
    boolean isEmpty() {
    boolean isEmpty() {
        return mChildren.isEmpty();
        return mChildren.isEmpty();
+24 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.wm;


import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
@@ -155,4 +156,27 @@ public class WindowTokenTests extends WindowTestsBase {
        assertTrue(token.mRoundedCornerOverlay);
        assertTrue(token.mRoundedCornerOverlay);
        assertTrue(token.mFromClientToken);
        assertTrue(token.mFromClientToken);
    }
    }

    /**
     * Test that {@link android.view.SurfaceControl} should not be created for the
     * {@link WindowToken} which was created for {@link android.app.WindowContext} initially, the
     * surface should be create after addWindow for this token.
     */
    @Test
    public void testSurfaceCreatedForWindowToken() {
        final WindowToken fromClientToken = new WindowToken(mDisplayContent.mWmService,
                mock(IBinder.class), TYPE_APPLICATION_OVERLAY, true /* persistOnEmpty */,
                mDisplayContent, true /* ownerCanManageAppTokens */,
                true /* roundedCornerOverlay */, true /* fromClientToken */);
        assertNull(fromClientToken.mSurfaceControl);

        createWindow(null, TYPE_APPLICATION_OVERLAY, fromClientToken, "window");
        assertNotNull(fromClientToken.mSurfaceControl);

        final WindowToken nonClientToken = new WindowToken(mDisplayContent.mWmService,
                mock(IBinder.class), TYPE_TOAST, true /* persistOnEmpty */, mDisplayContent,
                true /* ownerCanManageAppTokens */, true /* roundedCornerOverlay */,
                false /* fromClientToken */);
        assertNotNull(nonClientToken.mSurfaceControl);
    }
}
}