Merge "[MediaProjection] Do not start layer mirroring without a surface" into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
052c311bb2
@@ -82,6 +82,8 @@ public enum ProtoLogGroup implements IProtoLogGroup {
|
|||||||
Consts.TAG_WM),
|
Consts.TAG_WM),
|
||||||
WM_DEBUG_WINDOW_INSETS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
|
WM_DEBUG_WINDOW_INSETS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
|
||||||
Consts.TAG_WM),
|
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");
|
TEST_GROUP(true, true, false, "WindowManagerProtoLogTest");
|
||||||
|
|
||||||
private final boolean mEnabled;
|
private final boolean mEnabled;
|
||||||
|
|||||||
@@ -211,6 +211,12 @@
|
|||||||
"group": "WM_DEBUG_SYNC_ENGINE",
|
"group": "WM_DEBUG_SYNC_ENGINE",
|
||||||
"at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
|
"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": {
|
"-1895337367": {
|
||||||
"message": "Delete root task display=%d winMode=%d",
|
"message": "Delete root task display=%d winMode=%d",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -1093,6 +1099,12 @@
|
|||||||
"group": "WM_ERROR",
|
"group": "WM_ERROR",
|
||||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
"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": {
|
"-883738232": {
|
||||||
"message": "Adding more than one toast window for UID at a time.",
|
"message": "Adding more than one toast window for UID at a time.",
|
||||||
"level": "WARN",
|
"level": "WARN",
|
||||||
@@ -1303,6 +1315,12 @@
|
|||||||
"group": "WM_DEBUG_ORIENTATION",
|
"group": "WM_DEBUG_ORIENTATION",
|
||||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
"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": {
|
"-655104359": {
|
||||||
"message": "Frontmost changed immersion: %s",
|
"message": "Frontmost changed immersion: %s",
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
@@ -1561,6 +1579,12 @@
|
|||||||
"group": "WM_ERROR",
|
"group": "WM_ERROR",
|
||||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
"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": {
|
"-381475323": {
|
||||||
"message": "DisplayContent: boot is waiting for window of type %d to be drawn",
|
"message": "DisplayContent: boot is waiting for window of type %d to be drawn",
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
@@ -1633,6 +1657,12 @@
|
|||||||
"group": "WM_DEBUG_STATES",
|
"group": "WM_DEBUG_STATES",
|
||||||
"at": "com\/android\/server\/wm\/TaskFragment.java"
|
"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": {
|
"-302468788": {
|
||||||
"message": "Expected target rootTask=%s to be top most but found rootTask=%s",
|
"message": "Expected target rootTask=%s to be top most but found rootTask=%s",
|
||||||
"level": "WARN",
|
"level": "WARN",
|
||||||
@@ -1699,6 +1729,12 @@
|
|||||||
"group": "WM_DEBUG_WINDOW_MOVEMENT",
|
"group": "WM_DEBUG_WINDOW_MOVEMENT",
|
||||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
"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": {
|
"-177040661": {
|
||||||
"message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s",
|
"message": "Start rotation animation. customAnim=%s, mCurRotation=%s, mOriginalRotation=%s",
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
@@ -1795,6 +1831,12 @@
|
|||||||
"group": "WM_DEBUG_STATES",
|
"group": "WM_DEBUG_STATES",
|
||||||
"at": "com\/android\/server\/wm\/TaskFragment.java"
|
"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": {
|
"-70719599": {
|
||||||
"message": "Unregister remote animations for organizer=%s uid=%d pid=%d",
|
"message": "Unregister remote animations for organizer=%s uid=%d pid=%d",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -2347,6 +2389,12 @@
|
|||||||
"group": "WM_DEBUG_WINDOW_ORGANIZER",
|
"group": "WM_DEBUG_WINDOW_ORGANIZER",
|
||||||
"at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java"
|
"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": {
|
"508887531": {
|
||||||
"message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s",
|
"message": "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -3103,6 +3151,12 @@
|
|||||||
"group": "WM_DEBUG_SCREEN_ON",
|
"group": "WM_DEBUG_SCREEN_ON",
|
||||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
"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": {
|
"1417601133": {
|
||||||
"message": "Enqueueing ADD_STARTING",
|
"message": "Enqueueing ADD_STARTING",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -3349,6 +3403,12 @@
|
|||||||
"group": "WM_DEBUG_CONFIGURATION",
|
"group": "WM_DEBUG_CONFIGURATION",
|
||||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
"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": {
|
"1689989893": {
|
||||||
"message": "SyncGroup %d: Set ready",
|
"message": "SyncGroup %d: Set ready",
|
||||||
"level": "VERBOSE",
|
"level": "VERBOSE",
|
||||||
@@ -3753,6 +3813,9 @@
|
|||||||
"WM_DEBUG_KEEP_SCREEN_ON": {
|
"WM_DEBUG_KEEP_SCREEN_ON": {
|
||||||
"tag": "WindowManager"
|
"tag": "WindowManager"
|
||||||
},
|
},
|
||||||
|
"WM_DEBUG_LAYER_MIRRORING": {
|
||||||
|
"tag": "WindowManager"
|
||||||
|
},
|
||||||
"WM_DEBUG_LOCKTASK": {
|
"WM_DEBUG_LOCKTASK": {
|
||||||
"tag": "WindowManager"
|
"tag": "WindowManager"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -303,6 +303,9 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Point getDisplaySurfaceDefaultSize() {
|
public Point getDisplaySurfaceDefaultSize() {
|
||||||
|
if (mSurface == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return mSurface.getDefaultSize();
|
return mSurface.getDefaultSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
|
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_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_ORIENTATION;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
|
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;
|
@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;
|
private SurfaceControl mMirroredSurface = null;
|
||||||
|
|
||||||
@@ -314,6 +316,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
*/
|
*/
|
||||||
private Rect mLastMirroredDisplayAreaBounds = null;
|
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
|
// 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
|
// 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
|
// 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);
|
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display);
|
||||||
|
|
||||||
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
|
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() {
|
boolean isReady() {
|
||||||
@@ -2504,19 +2507,42 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
|
|
||||||
// Update mirroring surface for MediaProjection, if this DisplayContent is being used
|
// Update mirroring surface for MediaProjection, if this DisplayContent is being used
|
||||||
// for layer mirroring.
|
// for layer mirroring.
|
||||||
if (mMirroredSurface != null) {
|
if (isCurrentlyMirroring() && mLastMirroredDisplayAreaBounds != null) {
|
||||||
// Retrieve the size of the DisplayArea to mirror, and continue with the update if the
|
// Mirroring has already begun, but update mirroring since the display is now on.
|
||||||
// bounds have changed.
|
|
||||||
final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
|
final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
|
||||||
mTokenToMirror);
|
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
|
// Retrieve the size of the DisplayArea to mirror, and continue with the update
|
||||||
// if the bounds or orientation has changed.
|
// if the bounds or orientation has changed.
|
||||||
final Rect displayAreaBounds = wc.getDisplayContent().getBounds();
|
final Rect displayAreaBounds = wc.getDisplayContent().getBounds();
|
||||||
int displayAreaOrientation = wc.getDisplayContent().getOrientation();
|
int displayAreaOrientation = wc.getDisplayContent().getOrientation();
|
||||||
if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds)
|
if (!mLastMirroredDisplayAreaBounds.equals(displayAreaBounds)
|
||||||
|| lastOrientation != displayAreaOrientation) {
|
|| 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4405,6 +4431,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
|
mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
|
||||||
true /* inTraversal, must call performTraversalInTrans... below */);
|
true /* inTraversal, must call performTraversalInTrans... below */);
|
||||||
}
|
}
|
||||||
|
// If the display now has content, or no longer has content, update layer mirroring.
|
||||||
updateMirroring();
|
updateMirroring();
|
||||||
|
|
||||||
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
|
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
|
||||||
@@ -5504,6 +5531,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
} else if (displayState == Display.STATE_ON) {
|
} else if (displayState == Display.STATE_ON) {
|
||||||
mOffTokenAcquirer.release(mDisplayId);
|
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();
|
mWmService.requestTraversal();
|
||||||
}
|
}
|
||||||
@@ -5982,31 +6018,48 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
* back to original MediaProjection approach.
|
* back to original MediaProjection approach.
|
||||||
*/
|
*/
|
||||||
private void startMirrorIfNeeded() {
|
private void startMirrorIfNeeded() {
|
||||||
// Only mirror if this display does not have its own content.
|
// Only mirror if this display does not have its own content, is not mirroring already,
|
||||||
if (mLastHasContent) {
|
// and if this display is on (it has a surface to write output to).
|
||||||
|
if (mLastHasContent || isCurrentlyMirroring() || mDisplay.getState() == Display.STATE_OFF) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given the WindowToken of the DisplayArea to mirror, retrieve the associated
|
// Given the WindowToken of the DisplayArea to mirror, retrieve the associated
|
||||||
// SurfaceControl.
|
// SurfaceControl.
|
||||||
IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror(
|
IBinder tokenToMirror = mWmService.mDisplayManagerInternal.getWindowTokenClientToMirror(
|
||||||
mDisplayId);
|
mDisplayId);
|
||||||
|
|
||||||
if (tokenToMirror == null) {
|
if (tokenToMirror == null) {
|
||||||
// This DisplayContent instance is not involved in layer mirroring. If the display
|
// This DisplayContent instance is not involved in layer mirroring. If the display
|
||||||
// has been created for capturing, fall back to prior MediaProjection approach.
|
// has been created for capturing, fall back to prior MediaProjection approach.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
|
final WindowContainer wc = mWmService.mWindowContextListenerController.getContainer(
|
||||||
tokenToMirror);
|
tokenToMirror);
|
||||||
if (wc == null) {
|
if (wc == null) {
|
||||||
// Un-set the window token to mirror for this VirtualDisplay, to fall back to the
|
// Un-set the window token to mirror for this VirtualDisplay, to fall back to the
|
||||||
// original MediaProjection approach.
|
// original MediaProjection approach.
|
||||||
mWmService.mDisplayManagerInternal.setWindowTokenClientToMirror(mDisplayId, null);
|
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;
|
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.
|
// Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture.
|
||||||
|
SurfaceControl sc = wc.getDisplayContent().getSurfaceControl();
|
||||||
mMirroredSurface = SurfaceControl.mirrorSurface(sc);
|
mMirroredSurface = SurfaceControl.mirrorSurface(sc);
|
||||||
SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get()
|
SurfaceControl.Transaction transaction = mWmService.mTransactionFactory.get()
|
||||||
// Set the mMirroredSurface's parent to the root SurfaceControl for this
|
// 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.
|
// VirtualDisplay will show up as part of the mirrored content.
|
||||||
.reparent(mWindowingLayer, null);
|
.reparent(mWindowingLayer, null);
|
||||||
// Retrieve the size of the DisplayArea to mirror.
|
// Retrieve the size of the DisplayArea to mirror.
|
||||||
updateMirroredSurface(transaction, wc.getDisplayContent().getBounds());
|
updateMirroredSurface(transaction, wc.getDisplayContent().getBounds(), surfaceSize);
|
||||||
mTokenToMirror = tokenToMirror;
|
mTokenToMirror = tokenToMirror;
|
||||||
|
|
||||||
// No need to clean up. In SurfaceFlinger, parents hold references to their children. The
|
// 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() {
|
private void updateMirroring() {
|
||||||
if (mLastHasContent && mMirroredSurface != null) {
|
if (isCurrentlyMirroring() && (mLastHasContent
|
||||||
// Display now has content, so stop mirroring to it.
|
|| 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()
|
mWmService.mTransactionFactory.get()
|
||||||
// Remove the reference to mMirroredSurface, to clean up associated memory.
|
// Remove the reference to mMirroredSurface, to clean up associated memory.
|
||||||
.remove(mMirroredSurface)
|
.remove(mMirroredSurface)
|
||||||
@@ -6044,8 +6104,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
// Stop mirroring by destroying the reference to the mirrored layer.
|
// Stop mirroring by destroying the reference to the mirrored layer.
|
||||||
mMirroredSurface = null;
|
mMirroredSurface = null;
|
||||||
// Do not un-set the token, in case content is removed and mirroring should begin again.
|
// Do not un-set the token, in case content is removed and mirroring should begin again.
|
||||||
} else if (!mLastHasContent && mMirroredSurface == null) {
|
} else {
|
||||||
// Display no longer has content, so start mirroring to it.
|
// Display no longer has content, or now has a surface to write to, so try to start
|
||||||
|
// mirroring to it.
|
||||||
startMirrorIfNeeded();
|
startMirrorIfNeeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6058,17 +6119,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
* to. Transaction is not applied before returning.
|
* to. Transaction is not applied before returning.
|
||||||
* @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by
|
* @param displayAreaBounds bounds of the DisplayArea to mirror to the surface provided by
|
||||||
* the app.
|
* the app.
|
||||||
|
* @param surfaceSize the default size of the surface to write the display area content to
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void updateMirroredSurface(SurfaceControl.Transaction transaction,
|
void updateMirroredSurface(SurfaceControl.Transaction transaction,
|
||||||
Rect displayAreaBounds) {
|
Rect displayAreaBounds, Point surfaceSize) {
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the
|
// Calculate the scale to apply to the root mirror SurfaceControl to fit the size of the
|
||||||
// output surface.
|
// output surface.
|
||||||
float scaleX = surfaceSize.x / (float) displayAreaBounds.width();
|
float scaleX = surfaceSize.x / (float) displayAreaBounds.width();
|
||||||
@@ -6103,6 +6158,36 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mLastMirroredDisplayAreaBounds = new Rect(displayAreaBounds);
|
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}. */
|
/** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
|
||||||
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
|
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
|
||||||
|
|
||||||
|
|||||||
@@ -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_LANDSCAPE;
|
||||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
|
||||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
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.P;
|
||||||
import static android.os.Build.VERSION_CODES.Q;
|
import static android.os.Build.VERSION_CODES.Q;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
@@ -111,6 +112,7 @@ import android.graphics.Insets;
|
|||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Region;
|
import android.graphics.Region;
|
||||||
|
import android.hardware.display.VirtualDisplay;
|
||||||
import android.metrics.LogMaker;
|
import android.metrics.LogMaker;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -2292,7 +2294,7 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
float yScale = 2f;
|
float yScale = 2f;
|
||||||
Rect displayAreaBounds = new Rect(0, 0, Math.round(surfaceSize.x * xScale),
|
Rect displayAreaBounds = new Rect(0, 0, Math.round(surfaceSize.x * xScale),
|
||||||
Math.round(surfaceSize.y * yScale));
|
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.
|
// THEN content in the captured DisplayArea is scaled to fit the surface size.
|
||||||
verify(mTransaction, atLeastOnce()).setMatrix(mirroredSurface, 1.0f / yScale, 0, 0,
|
verify(mTransaction, atLeastOnce()).setMatrix(mirroredSurface, 1.0f / yScale, 0, 0,
|
||||||
@@ -2305,6 +2307,72 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
mockSession.finishMocking();
|
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 {
|
private class TestToken extends Binder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2342,6 +2410,11 @@ public class DisplayContentTests extends WindowTestsBase {
|
|||||||
return mirroredSurface;
|
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) {
|
private void removeRootTaskTests(Runnable runnable) {
|
||||||
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
|
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
|
||||||
final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
|
final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
|
||||||
|
|||||||
Reference in New Issue
Block a user