diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 6c69dc625a703..a49cffb664fdf 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -378,10 +378,7 @@ class WindowContainer extends ConfigurationContainer< if (mSurfaceControl == null) { // If we don't yet have a surface, but we now have a parent, we should // build a surface. - setSurfaceControl(makeSurface().build()); - getPendingTransaction().show(mSurfaceControl); - onSurfaceShown(getPendingTransaction()); - updateSurfacePosition(); + createSurfaceControl(false /*force*/); } else { // 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. @@ -399,6 +396,13 @@ class WindowContainer extends ConfigurationContainer< scheduleAnimation(); } + void createSurfaceControl(boolean force) { + setSurfaceControl(makeSurface().build()); + getPendingTransaction().show(mSurfaceControl); + onSurfaceShown(getPendingTransaction()); + updateSurfacePosition(); + } + /** * Called when the surface is shown for the first time. */ diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index f965f7b80ee94..850c36238513f 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -100,6 +100,9 @@ class WindowToken extends WindowContainer { private Configuration mLastReportedConfig; private int mLastReportedDisplay = INVALID_DISPLAY; + /** + * When set to {@code true}, this window token is created from {@link android.app.WindowContext} + */ @VisibleForTesting final boolean mFromClientToken; @@ -281,6 +284,11 @@ class WindowToken extends WindowContainer { // Child windows are added to their parent windows. 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)) { ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this); addChild(win, mWindowComparator); @@ -289,6 +297,13 @@ class WindowToken extends WindowContainer { } } + @Override + void createSurfaceControl(boolean force) { + if (!mFromClientToken || force) { + super.createSurfaceControl(force); + } + } + /** Returns true if the token windows list is empty. */ boolean isEmpty() { return mChildren.isEmpty(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java index 38f643daec270..7a347cb050be9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; 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_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static org.junit.Assert.assertEquals; @@ -155,4 +156,27 @@ public class WindowTokenTests extends WindowTestsBase { assertTrue(token.mRoundedCornerOverlay); 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); + } }