Loading core/java/com/android/internal/protolog/ProtoLogGroup.java +2 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,8 @@ public enum ProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM), WM_DEBUG_WINDOW_INSETS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM), WM_DEBUG_LAYER_MIRRORING(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM), TEST_GROUP(true, true, false, "WindowManagerProtoLogTest"); private final boolean mEnabled; Loading data/etc/services.core.protolog.json +63 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,12 @@ "group": "WM_DEBUG_SYNC_ENGINE", "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, "-1898316768": { "message": "Unable to retrieve window container to start layer mirroring for display %d", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-1895337367": { "message": "Delete root task display=%d winMode=%d", "level": "VERBOSE", Loading Loading @@ -1093,6 +1099,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-904499590": { "message": "Provided surface for layer mirroring on display %d is not present, so do not update the surface", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-883738232": { "message": "Adding more than one toast window for UID at a time.", "level": "WARN", Loading Loading @@ -1303,6 +1315,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, "-663411559": { "message": "Going ahead with updating layer mirroring for display %d to new bounds %s and\/or orientation %d.", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-655104359": { "message": "Frontmost changed immersion: %s", "level": "DEBUG", Loading Loading @@ -1561,6 +1579,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-384564722": { "message": "Unable to start layer mirroring for display %d since the surface is not available.", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-381475323": { "message": "DisplayContent: boot is waiting for window of type %d to be drawn", "level": "DEBUG", Loading Loading @@ -1633,6 +1657,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, "-309399422": { "message": "Display %d state is now (%d), so update layer mirroring?", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-302468788": { "message": "Expected target rootTask=%s to be top most but found rootTask=%s", "level": "WARN", Loading Loading @@ -1699,6 +1729,12 @@ "group": "WM_DEBUG_WINDOW_MOVEMENT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-190034097": { "message": "Unable to retrieve window container to update layer mirroring for display %d", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-177040661": { "message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s", "level": "DEBUG", Loading Loading @@ -1795,6 +1831,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, "-79877120": { "message": "Display %d has content (%b) so disable layer mirroring", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-70719599": { "message": "Unregister remote animations for organizer=%s uid=%d pid=%d", "level": "VERBOSE", Loading Loading @@ -2347,6 +2389,12 @@ "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, "504397469": { "message": "Unable to update layer mirroring for display %d to new bounds %s and\/or orientation %d, since the surface is not available.", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "508887531": { "message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", "level": "VERBOSE", Loading Loading @@ -3103,6 +3151,12 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "1407569006": { "message": "Display %d was already layer mirroring, so apply transformations if necessary", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "1417601133": { "message": "Enqueueing ADD_STARTING", "level": "VERBOSE", Loading Loading @@ -3349,6 +3403,12 @@ "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1687376052": { "message": "Display %d has no content and is on, so start layer mirroring for state %d", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "1689989893": { "message": "SyncGroup %d: Set ready", "level": "VERBOSE", Loading Loading @@ -3753,6 +3813,9 @@ "WM_DEBUG_KEEP_SCREEN_ON": { "tag": "WindowManager" }, "WM_DEBUG_LAYER_MIRRORING": { "tag": "WindowManager" }, "WM_DEBUG_LOCKTASK": { "tag": "WindowManager" }, Loading services/core/java/com/android/server/display/VirtualDisplayAdapter.java +3 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @Override public Point getDisplaySurfaceDefaultSize() { if (mSurface == null) { return null; } return mSurface.getDefaultSize(); } Loading services/core/java/com/android/server/wm/DisplayContent.java +123 −38 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LAYER_MIRRORING; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; Loading Loading @@ -305,7 +306,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @VisibleForTesting IBinder mTokenToMirror = null; /** * The surface for mirroring the contents of this hierarchy. * The surface for mirroring the contents of this hierarchy, or null if layer mirroring is * temporarily disabled. */ private SurfaceControl mMirroredSurface = null; Loading @@ -314,6 +316,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private Rect mLastMirroredDisplayAreaBounds = null; /** * The last state of the display. */ private int mLastDisplayState; // Contains all IME window containers. Note that the z-ordering of the IME windows will depend // on the IME target. We mainly have this container grouping so we can keep track of all the IME // window containers together and move them in-sync if/when needed. We use a subclass of Loading Loading @@ -1142,10 +1149,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display); mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this); // Check if this DisplayContent is for a new VirtualDisplay, that should use layer mirroring // to capture the contents of a DisplayArea. startMirrorIfNeeded(); } boolean isReady() { Loading Loading @@ -2504,19 +2507,42 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Update mirroring surface for MediaProjection, if this DisplayContent is being used // for layer mirroring. if (mMirroredSurface != null) { // Retrieve the size of the DisplayArea to mirror, and continue with the update if the // bounds have changed. if (isCurrentlyMirroring() && mLastMirroredDisplayAreaBounds != null) { // Mirroring has already begun, but update mirroring since the display is now on. final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer( mTokenToMirror); if (wc != null && mLastMirroredDisplayAreaBounds != null) { if (wc == null) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to retrieve window container to update layer mirroring for " + "display %d", mDisplayId); return; } ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d was already layer mirroring, so apply transformations if necessary", mDisplayId); // Retrieve the size of the DisplayArea to mirror, and continue with the update // if the bounds or orientation has changed. final Rect displayAreaBounds = wc.getDisplayContent().getBounds(); int displayAreaOrientation = wc.getDisplayContent().getOrientation(); if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds) || lastOrientation != displayAreaOrientation) { updateMirroredSurface(mWmService.mTransactionFactory.get(), displayAreaBounds); Point surfaceSize = fetchSurfaceSizeIfPresent(); if (surfaceSize != null) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Going ahead with updating layer mirroring for display %d to new " + "bounds %s and/or orientation %d.", mDisplayId, displayAreaBounds, displayAreaOrientation); updateMirroredSurface(mWmService.mTransactionFactory.get(), displayAreaBounds, surfaceSize); } else { // If the surface removed, do nothing. We will handle this via onDisplayChanged // (the display will be off if the surface is removed). ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to update layer mirroring for display %d to new bounds %s" + " and/or orientation %d, since the surface is not available.", mDisplayId, displayAreaBounds, displayAreaOrientation); } } } Loading Loading @@ -4405,6 +4431,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing, true /* inTraversal, must call performTraversalInTrans... below */); } // If the display now has content, or no longer has content, update layer mirroring. updateMirroring(); final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible(); Loading Loading @@ -5504,6 +5531,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } else if (displayState == Display.STATE_ON) { mOffTokenAcquirer.release(mDisplayId); } ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d state is now (%d), so update layer mirroring?", mDisplayId, displayState); if (mLastDisplayState != displayState) { // If state is on due to surface being added, then start layer mirroring. // If state is off due to surface being removed, then stop layer mirroring. updateMirroring(); } mLastDisplayState = displayState; } mWmService.requestTraversal(); } Loading Loading @@ -5982,31 +6018,48 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * back to original MediaProjection approach. */ private void startMirrorIfNeeded() { // Only mirror if this display does not have its own content. if (mLastHasContent) { // Only mirror if this display does not have its own content, is not mirroring already, // and if this display is on (it has a surface to write output to). if (mLastHasContent || isCurrentlyMirroring() || mDisplay.getState() == Display.STATE_OFF) { return; } // Given the WindowToken of the DisplayArea to mirror, retrieve the associated // SurfaceControl. IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror( mDisplayId); if (tokenToMirror == null) { // This DisplayContent instance is not involved in layer mirroring. If the display // has been created for capturing, fall back to prior MediaProjection approach. return; } final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer( tokenToMirror); if (wc == null) { // Un-set the window token to mirror for this VirtualDisplay, to fall back to the // original MediaProjection approach. mWmService.mDisplayManagerInternal.setWindowTokenClientToMirror(mDisplayId, null); ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to retrieve window container to start layer mirroring for display %d", mDisplayId); return; } SurfaceControl sc = wc.getDisplayContent().getSurfaceControl(); Point surfaceSize = fetchSurfaceSizeIfPresent(); if (surfaceSize == null) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to start layer mirroring for display %d since the surface is not " + "available.", mDisplayId); return; } ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d has no content and is on, so start layer mirroring for state %d", mDisplayId, mDisplay.getState()); // Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture. SurfaceControl sc = wc.getDisplayContent().getSurfaceControl(); mMirroredSurface = SurfaceControl.mirrorSurface(sc); SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get() // Set the mMirroredSurface's parent to the root SurfaceControl for this Loading @@ -6019,7 +6072,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // VirtualDisplay will show up as part of the mirrored content. .reparent(mWindowingLayer, null); // Retrieve the size of the DisplayArea to mirror. updateMirroredSurface(transaction, wc.getDisplayContent().getBounds()); updateMirroredSurface(transaction, wc.getDisplayContent().getBounds(), surfaceSize); mTokenToMirror = tokenToMirror; // No need to clean up. In SurfaceFlinger, parents hold references to their children. The Loading @@ -6029,11 +6082,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } /** * Start or stop mirroring if this DisplayContent now has content, or no longer has content. * Start mirroring if this DisplayContent no longer has content. Stop mirroring if it now * has content or the display is not on. */ private void updateMirroring() { if (mLastHasContent && mMirroredSurface != null) { // Display now has content, so stop mirroring to it. if (isCurrentlyMirroring() && (mLastHasContent || mDisplay.getState() == Display.STATE_OFF)) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d has content (%b) so disable layer mirroring", mDisplayId, mLastHasContent); // If the display is not on and it is a virtual display, then it no longer has an // associated surface to write output to. // If the display now has content, stop mirroring to it. mWmService.mTransactionFactory.get() // Remove the reference to mMirroredSurface, to clean up associated memory. .remove(mMirroredSurface) Loading @@ -6044,8 +6104,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Stop mirroring by destroying the reference to the mirrored layer. mMirroredSurface = null; // Do not un-set the token, in case content is removed and mirroring should begin again. } else if (!mLastHasContent && mMirroredSurface == null) { // Display no longer has content, so start mirroring to it. } else { // Display no longer has content, or now has a surface to write to, so try to start // mirroring to it. startMirrorIfNeeded(); } } Loading @@ -6058,17 +6119,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * to. Transaction is not applied before returning. * @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by * the app. * @param surfaceSize the default size of the surface to write the display area content to */ @VisibleForTesting void updateMirroredSurface(SurfaceControl.Transaction transaction, Rect displayAreaBounds) { // Retrieve the default size of the surface the app provided to // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface, // since it reads out buffers from the surface, and SurfaceFlinger is the producer since // it writes the mirrored layers to the buffers. final Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize( mDisplayId); Rect displayAreaBounds, Point surfaceSize) { // Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the // output surface. float scaleX = surfaceSize.x / (float) displayAreaBounds.width(); Loading Loading @@ -6103,6 +6158,36 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mLastMirroredDisplayAreaBounds = new Rect(displayAreaBounds); } /** * Returns a non-null {@link Point} if the surface is present, or null otherwise */ Point fetchSurfaceSizeIfPresent() { // Retrieve the default size of the surface the app provided to // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface, // since it reads out buffers from the surface, and SurfaceFlinger is the producer since // it writes the mirrored layers to the buffers. Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize( mDisplayId); if (surfaceSize == null) { // Layer mirroring started with a null surface, so do not apply any transformations yet. // State of virtual display will change to 'ON' when the surface is set. // will get event DISPLAY_DEVICE_EVENT_CHANGED ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Provided surface for layer mirroring on display %d is not present, so do not" + " update the surface", mDisplayId); return null; } return surfaceSize; } /** * Returns {@code true} if this DisplayContent is currently layer mirroring. */ boolean isCurrentlyMirroring() { return mTokenToMirror != null && mMirroredSurface != null; } /** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */ class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener { Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +74 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; import static android.os.Build.VERSION_CODES.P; import static android.os.Build.VERSION_CODES.Q; import static android.view.Display.DEFAULT_DISPLAY; Loading Loading @@ -111,6 +112,7 @@ import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.VirtualDisplay; import android.metrics.LogMaker; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -2292,7 +2294,7 @@ public class DisplayContentTests extends WindowTestsBase { float yScale = 2f; Rect displayAreaBounds = new Rect(0, 0, Math.round(surfaceSize.x * xScale), Math.round(surfaceSize.y * yScale)); virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds); virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds, surfaceSize); // THEN content in the captured DisplayArea is scaled to fit the surface size. verify(mTransaction, atLeastOnce()).setMatrix(mirroredSurface, 1.0f / yScale, 0, 0, Loading @@ -2305,6 +2307,72 @@ public class DisplayContentTests extends WindowTestsBase { mockSession.finishMocking(); } @Test public void testVirtualDisplayContent_withoutSurface() { MockitoSession mockSession = mockitoSession() .initMocks(this) .spyStatic(SurfaceControl.class) .strictness(Strictness.LENIENT) .startMocking(); // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to // mirror. setUpDefaultTaskDisplayAreaWindowToken(); // GIVEN SurfaceControl can successfully mirror the provided surface. Point surfaceSize = new Point( mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(), mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height()); surfaceControlMirrors(surfaceSize); // GIVEN a new VirtualDisplay with an associated surface. final VirtualDisplay display = createVirtualDisplay(surfaceSize, null /* surface */); final int displayId = display.getDisplay().getDisplayId(); mWm.mRoot.onDisplayAdded(displayId); // WHEN getting the DisplayContent for the new virtual display. DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId); // THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off. assertThat(actualDC.mTokenToMirror).isNull(); display.release(); mockSession.finishMocking(); } @Test public void testVirtualDisplayContent_withSurface() { MockitoSession mockSession = mockitoSession() .initMocks(this) .spyStatic(SurfaceControl.class) .strictness(Strictness.LENIENT) .startMocking(); // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to // mirror. final IBinder tokenToMirror = setUpDefaultTaskDisplayAreaWindowToken(); // GIVEN SurfaceControl can successfully mirror the provided surface. Point surfaceSize = new Point( mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(), mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height()); surfaceControlMirrors(surfaceSize); // GIVEN a new VirtualDisplay with an associated surface. final VirtualDisplay display = createVirtualDisplay(surfaceSize, new Surface()); final int displayId = display.getDisplay().getDisplayId(); mWm.mRoot.onDisplayAdded(displayId); // WHEN getting the DisplayContent for the new virtual display. DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId); // THEN mirroring is initiated for the default display's DisplayArea. assertThat(actualDC.mTokenToMirror).isEqualTo(tokenToMirror); display.release(); mockSession.finishMocking(); } private class TestToken extends Binder { } Loading Loading @@ -2342,6 +2410,11 @@ public class DisplayContentTests extends WindowTestsBase { return mirroredSurface; } private VirtualDisplay createVirtualDisplay(Point size, Surface surface) { return mWm.mDisplayManager.createVirtualDisplay("VirtualDisplay", size.x, size.y, DisplayMetrics.DENSITY_140, surface, VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR); } private void removeRootTaskTests(Runnable runnable) { final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, Loading Loading
core/java/com/android/internal/protolog/ProtoLogGroup.java +2 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,8 @@ public enum ProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM), WM_DEBUG_WINDOW_INSETS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM), WM_DEBUG_LAYER_MIRRORING(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM), TEST_GROUP(true, true, false, "WindowManagerProtoLogTest"); private final boolean mEnabled; Loading
data/etc/services.core.protolog.json +63 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,12 @@ "group": "WM_DEBUG_SYNC_ENGINE", "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, "-1898316768": { "message": "Unable to retrieve window container to start layer mirroring for display %d", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-1895337367": { "message": "Delete root task display=%d winMode=%d", "level": "VERBOSE", Loading Loading @@ -1093,6 +1099,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-904499590": { "message": "Provided surface for layer mirroring on display %d is not present, so do not update the surface", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-883738232": { "message": "Adding more than one toast window for UID at a time.", "level": "WARN", Loading Loading @@ -1303,6 +1315,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/RootWindowContainer.java" }, "-663411559": { "message": "Going ahead with updating layer mirroring for display %d to new bounds %s and\/or orientation %d.", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-655104359": { "message": "Frontmost changed immersion: %s", "level": "DEBUG", Loading Loading @@ -1561,6 +1579,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-384564722": { "message": "Unable to start layer mirroring for display %d since the surface is not available.", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-381475323": { "message": "DisplayContent: boot is waiting for window of type %d to be drawn", "level": "DEBUG", Loading Loading @@ -1633,6 +1657,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, "-309399422": { "message": "Display %d state is now (%d), so update layer mirroring?", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-302468788": { "message": "Expected target rootTask=%s to be top most but found rootTask=%s", "level": "WARN", Loading Loading @@ -1699,6 +1729,12 @@ "group": "WM_DEBUG_WINDOW_MOVEMENT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "-190034097": { "message": "Unable to retrieve window container to update layer mirroring for display %d", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-177040661": { "message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s", "level": "DEBUG", Loading Loading @@ -1795,6 +1831,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/TaskFragment.java" }, "-79877120": { "message": "Display %d has content (%b) so disable layer mirroring", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "-70719599": { "message": "Unregister remote animations for organizer=%s uid=%d pid=%d", "level": "VERBOSE", Loading Loading @@ -2347,6 +2389,12 @@ "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, "504397469": { "message": "Unable to update layer mirroring for display %d to new bounds %s and\/or orientation %d, since the surface is not available.", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "508887531": { "message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", "level": "VERBOSE", Loading Loading @@ -3103,6 +3151,12 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "1407569006": { "message": "Display %d was already layer mirroring, so apply transformations if necessary", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "1417601133": { "message": "Enqueueing ADD_STARTING", "level": "VERBOSE", Loading Loading @@ -3349,6 +3403,12 @@ "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "1687376052": { "message": "Display %d has no content and is on, so start layer mirroring for state %d", "level": "VERBOSE", "group": "WM_DEBUG_LAYER_MIRRORING", "at": "com\/android\/server\/wm\/DisplayContent.java" }, "1689989893": { "message": "SyncGroup %d: Set ready", "level": "VERBOSE", Loading Loading @@ -3753,6 +3813,9 @@ "WM_DEBUG_KEEP_SCREEN_ON": { "tag": "WindowManager" }, "WM_DEBUG_LAYER_MIRRORING": { "tag": "WindowManager" }, "WM_DEBUG_LOCKTASK": { "tag": "WindowManager" }, Loading
services/core/java/com/android/server/display/VirtualDisplayAdapter.java +3 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter { @Override public Point getDisplaySurfaceDefaultSize() { if (mSurface == null) { return null; } return mSurface.getDefaultSize(); } Loading
services/core/java/com/android/server/wm/DisplayContent.java +123 −38 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LAYER_MIRRORING; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON; import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; Loading Loading @@ -305,7 +306,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @VisibleForTesting IBinder mTokenToMirror = null; /** * The surface for mirroring the contents of this hierarchy. * The surface for mirroring the contents of this hierarchy, or null if layer mirroring is * temporarily disabled. */ private SurfaceControl mMirroredSurface = null; Loading @@ -314,6 +316,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private Rect mLastMirroredDisplayAreaBounds = null; /** * The last state of the display. */ private int mLastDisplayState; // Contains all IME window containers. Note that the z-ordering of the IME windows will depend // on the IME target. We mainly have this container grouping so we can keep track of all the IME // window containers together and move them in-sync if/when needed. We use a subclass of Loading Loading @@ -1142,10 +1149,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display); mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this); // Check if this DisplayContent is for a new VirtualDisplay, that should use layer mirroring // to capture the contents of a DisplayArea. startMirrorIfNeeded(); } boolean isReady() { Loading Loading @@ -2504,19 +2507,42 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Update mirroring surface for MediaProjection, if this DisplayContent is being used // for layer mirroring. if (mMirroredSurface != null) { // Retrieve the size of the DisplayArea to mirror, and continue with the update if the // bounds have changed. if (isCurrentlyMirroring() && mLastMirroredDisplayAreaBounds != null) { // Mirroring has already begun, but update mirroring since the display is now on. final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer( mTokenToMirror); if (wc != null && mLastMirroredDisplayAreaBounds != null) { if (wc == null) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to retrieve window container to update layer mirroring for " + "display %d", mDisplayId); return; } ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d was already layer mirroring, so apply transformations if necessary", mDisplayId); // Retrieve the size of the DisplayArea to mirror, and continue with the update // if the bounds or orientation has changed. final Rect displayAreaBounds = wc.getDisplayContent().getBounds(); int displayAreaOrientation = wc.getDisplayContent().getOrientation(); if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds) || lastOrientation != displayAreaOrientation) { updateMirroredSurface(mWmService.mTransactionFactory.get(), displayAreaBounds); Point surfaceSize = fetchSurfaceSizeIfPresent(); if (surfaceSize != null) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Going ahead with updating layer mirroring for display %d to new " + "bounds %s and/or orientation %d.", mDisplayId, displayAreaBounds, displayAreaOrientation); updateMirroredSurface(mWmService.mTransactionFactory.get(), displayAreaBounds, surfaceSize); } else { // If the surface removed, do nothing. We will handle this via onDisplayChanged // (the display will be off if the surface is removed). ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to update layer mirroring for display %d to new bounds %s" + " and/or orientation %d, since the surface is not available.", mDisplayId, displayAreaBounds, displayAreaOrientation); } } } Loading Loading @@ -4405,6 +4431,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing, true /* inTraversal, must call performTraversalInTrans... below */); } // If the display now has content, or no longer has content, update layer mirroring. updateMirroring(); final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible(); Loading Loading @@ -5504,6 +5531,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } else if (displayState == Display.STATE_ON) { mOffTokenAcquirer.release(mDisplayId); } ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d state is now (%d), so update layer mirroring?", mDisplayId, displayState); if (mLastDisplayState != displayState) { // If state is on due to surface being added, then start layer mirroring. // If state is off due to surface being removed, then stop layer mirroring. updateMirroring(); } mLastDisplayState = displayState; } mWmService.requestTraversal(); } Loading Loading @@ -5982,31 +6018,48 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * back to original MediaProjection approach. */ private void startMirrorIfNeeded() { // Only mirror if this display does not have its own content. if (mLastHasContent) { // Only mirror if this display does not have its own content, is not mirroring already, // and if this display is on (it has a surface to write output to). if (mLastHasContent || isCurrentlyMirroring() || mDisplay.getState() == Display.STATE_OFF) { return; } // Given the WindowToken of the DisplayArea to mirror, retrieve the associated // SurfaceControl. IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror( mDisplayId); if (tokenToMirror == null) { // This DisplayContent instance is not involved in layer mirroring. If the display // has been created for capturing, fall back to prior MediaProjection approach. return; } final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer( tokenToMirror); if (wc == null) { // Un-set the window token to mirror for this VirtualDisplay, to fall back to the // original MediaProjection approach. mWmService.mDisplayManagerInternal.setWindowTokenClientToMirror(mDisplayId, null); ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to retrieve window container to start layer mirroring for display %d", mDisplayId); return; } SurfaceControl sc = wc.getDisplayContent().getSurfaceControl(); Point surfaceSize = fetchSurfaceSizeIfPresent(); if (surfaceSize == null) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Unable to start layer mirroring for display %d since the surface is not " + "available.", mDisplayId); return; } ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d has no content and is on, so start layer mirroring for state %d", mDisplayId, mDisplay.getState()); // Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture. SurfaceControl sc = wc.getDisplayContent().getSurfaceControl(); mMirroredSurface = SurfaceControl.mirrorSurface(sc); SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get() // Set the mMirroredSurface's parent to the root SurfaceControl for this Loading @@ -6019,7 +6072,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // VirtualDisplay will show up as part of the mirrored content. .reparent(mWindowingLayer, null); // Retrieve the size of the DisplayArea to mirror. updateMirroredSurface(transaction, wc.getDisplayContent().getBounds()); updateMirroredSurface(transaction, wc.getDisplayContent().getBounds(), surfaceSize); mTokenToMirror = tokenToMirror; // No need to clean up. In SurfaceFlinger, parents hold references to their children. The Loading @@ -6029,11 +6082,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } /** * Start or stop mirroring if this DisplayContent now has content, or no longer has content. * Start mirroring if this DisplayContent no longer has content. Stop mirroring if it now * has content or the display is not on. */ private void updateMirroring() { if (mLastHasContent && mMirroredSurface != null) { // Display now has content, so stop mirroring to it. if (isCurrentlyMirroring() && (mLastHasContent || mDisplay.getState() == Display.STATE_OFF)) { ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d has content (%b) so disable layer mirroring", mDisplayId, mLastHasContent); // If the display is not on and it is a virtual display, then it no longer has an // associated surface to write output to. // If the display now has content, stop mirroring to it. mWmService.mTransactionFactory.get() // Remove the reference to mMirroredSurface, to clean up associated memory. .remove(mMirroredSurface) Loading @@ -6044,8 +6104,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Stop mirroring by destroying the reference to the mirrored layer. mMirroredSurface = null; // Do not un-set the token, in case content is removed and mirroring should begin again. } else if (!mLastHasContent && mMirroredSurface == null) { // Display no longer has content, so start mirroring to it. } else { // Display no longer has content, or now has a surface to write to, so try to start // mirroring to it. startMirrorIfNeeded(); } } Loading @@ -6058,17 +6119,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * to. Transaction is not applied before returning. * @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by * the app. * @param surfaceSize the default size of the surface to write the display area content to */ @VisibleForTesting void updateMirroredSurface(SurfaceControl.Transaction transaction, Rect displayAreaBounds) { // Retrieve the default size of the surface the app provided to // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface, // since it reads out buffers from the surface, and SurfaceFlinger is the producer since // it writes the mirrored layers to the buffers. final Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize( mDisplayId); Rect displayAreaBounds, Point surfaceSize) { // Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the // output surface. float scaleX = surfaceSize.x / (float) displayAreaBounds.width(); Loading Loading @@ -6103,6 +6158,36 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mLastMirroredDisplayAreaBounds = new Rect(displayAreaBounds); } /** * Returns a non-null {@link Point} if the surface is present, or null otherwise */ Point fetchSurfaceSizeIfPresent() { // Retrieve the default size of the surface the app provided to // MediaProjection#createVirtualDisplay. Note the app is the consumer of the surface, // since it reads out buffers from the surface, and SurfaceFlinger is the producer since // it writes the mirrored layers to the buffers. Point surfaceSize = mWmService.mDisplayManagerInternal.getDisplaySurfaceDefaultSize( mDisplayId); if (surfaceSize == null) { // Layer mirroring started with a null surface, so do not apply any transformations yet. // State of virtual display will change to 'ON' when the surface is set. // will get event DISPLAY_DEVICE_EVENT_CHANGED ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Provided surface for layer mirroring on display %d is not present, so do not" + " update the surface", mDisplayId); return null; } return surfaceSize; } /** * Returns {@code true} if this DisplayContent is currently layer mirroring. */ boolean isCurrentlyMirroring() { return mTokenToMirror != null && mMirroredSurface != null; } /** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */ class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener { Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +74 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; import static android.os.Build.VERSION_CODES.P; import static android.os.Build.VERSION_CODES.Q; import static android.view.Display.DEFAULT_DISPLAY; Loading Loading @@ -111,6 +112,7 @@ import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.VirtualDisplay; import android.metrics.LogMaker; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -2292,7 +2294,7 @@ public class DisplayContentTests extends WindowTestsBase { float yScale = 2f; Rect displayAreaBounds = new Rect(0, 0, Math.round(surfaceSize.x * xScale), Math.round(surfaceSize.y * yScale)); virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds); virtualDisplay.updateMirroredSurface(mTransaction, displayAreaBounds, surfaceSize); // THEN content in the captured DisplayArea is scaled to fit the surface size. verify(mTransaction, atLeastOnce()).setMatrix(mirroredSurface, 1.0f / yScale, 0, 0, Loading @@ -2305,6 +2307,72 @@ public class DisplayContentTests extends WindowTestsBase { mockSession.finishMocking(); } @Test public void testVirtualDisplayContent_withoutSurface() { MockitoSession mockSession = mockitoSession() .initMocks(this) .spyStatic(SurfaceControl.class) .strictness(Strictness.LENIENT) .startMocking(); // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to // mirror. setUpDefaultTaskDisplayAreaWindowToken(); // GIVEN SurfaceControl can successfully mirror the provided surface. Point surfaceSize = new Point( mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(), mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height()); surfaceControlMirrors(surfaceSize); // GIVEN a new VirtualDisplay with an associated surface. final VirtualDisplay display = createVirtualDisplay(surfaceSize, null /* surface */); final int displayId = display.getDisplay().getDisplayId(); mWm.mRoot.onDisplayAdded(displayId); // WHEN getting the DisplayContent for the new virtual display. DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId); // THEN mirroring is not started, since a null surface indicates the VirtualDisplay is off. assertThat(actualDC.mTokenToMirror).isNull(); display.release(); mockSession.finishMocking(); } @Test public void testVirtualDisplayContent_withSurface() { MockitoSession mockSession = mockitoSession() .initMocks(this) .spyStatic(SurfaceControl.class) .strictness(Strictness.LENIENT) .startMocking(); // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to // mirror. final IBinder tokenToMirror = setUpDefaultTaskDisplayAreaWindowToken(); // GIVEN SurfaceControl can successfully mirror the provided surface. Point surfaceSize = new Point( mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().width(), mDefaultDisplay.getDefaultTaskDisplayArea().getBounds().height()); surfaceControlMirrors(surfaceSize); // GIVEN a new VirtualDisplay with an associated surface. final VirtualDisplay display = createVirtualDisplay(surfaceSize, new Surface()); final int displayId = display.getDisplay().getDisplayId(); mWm.mRoot.onDisplayAdded(displayId); // WHEN getting the DisplayContent for the new virtual display. DisplayContent actualDC = mWm.mRoot.getDisplayContent(displayId); // THEN mirroring is initiated for the default display's DisplayArea. assertThat(actualDC.mTokenToMirror).isEqualTo(tokenToMirror); display.release(); mockSession.finishMocking(); } private class TestToken extends Binder { } Loading Loading @@ -2342,6 +2410,11 @@ public class DisplayContentTests extends WindowTestsBase { return mirroredSurface; } private VirtualDisplay createVirtualDisplay(Point size, Surface surface) { return mWm.mDisplayManager.createVirtualDisplay("VirtualDisplay", size.x, size.y, DisplayMetrics.DENSITY_140, surface, VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR); } private void removeRootTaskTests(Runnable runnable) { final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, Loading