summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Naomi Musgrave <nmusgrave@google.com> 2021-09-06 09:57:30 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-09-06 09:57:30 +0000
commit052c311bb21e2cebee61dd104466cc2613dacf01 (patch)
tree08a6bfb894dc29fce34cb422802a166628c5a19c
parent506fa0bebd0e9ee013eaa5b15868a2ea4a379493 (diff)
parentfcef782559e0dcfeffb7c000f8c80c1259f89fad (diff)
Merge "[MediaProjection] Do not start layer mirroring without a surface" into sc-v2-dev
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogGroup.java2
-rw-r--r--data/etc/services.core.protolog.json63
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java161
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java75
5 files changed, 265 insertions, 39 deletions
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 0f153bcdf1d4..db019a67772f 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -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;
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 6a93761454f1..0d7225be9e03 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -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",
@@ -3753,6 +3813,9 @@
"WM_DEBUG_KEEP_SCREEN_ON": {
"tag": "WindowManager"
},
+ "WM_DEBUG_LAYER_MIRRORING": {
+ "tag": "WindowManager"
+ },
"WM_DEBUG_LOCKTASK": {
"tag": "WindowManager"
},
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 34d2b0160c3c..a59219265e2c 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -303,6 +303,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
@Override
public Point getDisplaySurfaceDefaultSize() {
+ if (mSurface == null) {
+ return null;
+ }
return mSurface.getDefaultSize();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b110d8d44fc5..71c41e43ac2e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -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;
@@ -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;
@@ -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
@@ -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() {
@@ -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) {
- // 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);
+ 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) {
+ 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);
}
}
}
@@ -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();
@@ -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();
}
@@ -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
@@ -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
@@ -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)
@@ -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();
}
}
@@ -6054,21 +6115,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* Apply transformations to the mirrored surface to ensure the captured contents are scaled to
* fit and centred in the output surface.
*
- * @param transaction the transaction to include transformations of mMirroredSurface
- * to. Transaction is not applied before returning.
- * @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by
- * the app.
+ * @param transaction the transaction to include transformations of mMirroredSurface
+ * 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();
@@ -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 {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 14dc33e5840b..4ee0c6090504 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -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;
@@ -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;
@@ -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,
@@ -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 {
}
@@ -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,