From 6af81a2bd62661ab4b426aa1901be18500e1cd24 Mon Sep 17 00:00:00 2001 From: Vaibhav Devmurari Date: Thu, 30 Jun 2022 17:11:55 +0000 Subject: [PATCH 1/2] Revert change "Change Rounded corner overlay to be in Overlay layer" Revert CL ag/18494304 Reason: Memory regression on certain devices (b/235601833) Bug: 235601833 Bug: 225505986 Test: manual Merged-In: Iddc0f36739ec1579e31edec314e9509c3c70edfb Change-Id: Iddc0f36739ec1579e31edec314e9509c3c70edfb (cherry picked from commit f62e00134726eacb2e7f19c287cfab0151b43025) --- .../com/android/server/input/GestureMonitorSpyWindow.java | 6 +----- .../server/inputmethod/HandwritingEventReceiverSurface.java | 5 +---- .../java/com/android/server/policy/WindowManagerPolicy.java | 4 ---- .../java/com/android/server/wm/InputManagerCallback.java | 2 +- .../java/com/android/server/wm/ScreenRotationAnimation.java | 5 ----- .../java/com/android/server/wm/WindowManagerService.java | 2 +- services/core/java/com/android/server/wm/WindowToken.java | 4 ++-- 7 files changed, 6 insertions(+), 22 deletions(-) diff --git a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java index e222c644da9e9..d238dae634adf 100644 --- a/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java +++ b/services/core/java/com/android/server/input/GestureMonitorSpyWindow.java @@ -27,8 +27,6 @@ import android.view.InputWindowHandle; import android.view.SurfaceControl; import android.view.WindowManager; -import com.android.server.policy.WindowManagerPolicy; - /** * An internal implementation of an {@link InputMonitor} that uses a spy window. * @@ -69,9 +67,7 @@ class GestureMonitorSpyWindow { final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); t.setInputWindowInfo(mInputSurface, mWindowHandle); - // Gesture monitor should be above handwriting event surface, hence setting it to - // WindowManagerPolicy.INPUT_DISPLAY_OVERLAY_LAYER + 1 - t.setLayer(mInputSurface, WindowManagerPolicy.INPUT_DISPLAY_OVERLAY_LAYER + 1); + t.setLayer(mInputSurface, Integer.MAX_VALUE); t.setPosition(mInputSurface, 0, 0); t.setCrop(mInputSurface, null /* crop to parent surface */); t.show(mInputSurface); diff --git a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java index 5438faa8793e3..8180e66166d93 100644 --- a/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java +++ b/services/core/java/com/android/server/inputmethod/HandwritingEventReceiverSurface.java @@ -27,8 +27,6 @@ import android.view.InputWindowHandle; import android.view.SurfaceControl; import android.view.WindowManager; -import com.android.server.policy.WindowManagerPolicy; - final class HandwritingEventReceiverSurface { public static final String TAG = HandwritingEventReceiverSurface.class.getSimpleName(); @@ -38,8 +36,7 @@ final class HandwritingEventReceiverSurface { // is above gesture monitors, then edge-back and swipe-up gestures won't work when this surface // is intercepting. // TODO(b/217538817): Specify the ordering in WM by usage. - private static final int HANDWRITING_SURFACE_LAYER = - WindowManagerPolicy.INPUT_DISPLAY_OVERLAY_LAYER; + private static final int HANDWRITING_SURFACE_LAYER = Integer.MAX_VALUE - 1; private final InputWindowHandle mWindowHandle; private final InputChannel mClientChannel; diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 89178139ffec2..7ca09ab5154f4 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -156,10 +156,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { int FINISH_LAYOUT_REDO_ANIM = 0x0008; /** Layer for the screen off animation */ int COLOR_FADE_LAYER = 0x40000001; - /** Layer for Input overlays for capturing inputs for gesture detection, etc. */ - int INPUT_DISPLAY_OVERLAY_LAYER = 0x7f000000; - /** Layer for Screen Decoration: The top most visible layer just below input overlay layers */ - int SCREEN_DECOR_DISPLAY_OVERLAY_LAYER = INPUT_DISPLAY_OVERLAY_LAYER - 1; /** * Register shortcuts for window manager to dispatch. diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index b7ddbd070460c..33cdd2e98113d 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -265,7 +265,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal .setContainerLayer() .setName(name) .setCallsite("createSurfaceForGestureMonitor") - .setParent(dc.getOverlayLayer()) + .setParent(dc.getSurfaceControl()) .build(); } } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index f80e732c8212a..bee44def1512d 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -173,11 +173,6 @@ class ScreenRotationAnimation { if (isSizeChanged) { mRoundedCornerOverlay = displayContent.findRoundedCornerOverlays(); - } else { - // Exclude rounded corner overlay from screenshot buffer. Rounded - // corner overlay windows are un-rotated during rotation animation - // for a seamless transition. - builder.setExcludeLayers(displayContent.findRoundedCornerOverlays()); } SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 52af39ee64b31..902218621cd00 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -8215,7 +8215,7 @@ public class WindowManagerService extends IWindowManager.Stub .setContainerLayer() .setName("IME Handwriting Surface") .setCallsite("getHandwritingSurfaceForDisplay") - .setParent(dc.getOverlayLayer()) + .setParent(dc.getSurfaceControl()) .build(); } } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 18f60b1a9a20e..d2e56faa0914c 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -368,7 +368,7 @@ class WindowToken extends WindowContainer { super.assignRelativeLayer(t, mDisplayContent.getDefaultTaskDisplayArea().getSplitScreenDividerAnchor(), 1); } else if (mRoundedCornerOverlay) { - super.assignLayer(t, WindowManagerPolicy.SCREEN_DECOR_DISPLAY_OVERLAY_LAYER); + super.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1); } else { super.assignLayer(t, layer); } @@ -378,7 +378,7 @@ class WindowToken extends WindowContainer { SurfaceControl.Builder makeSurface() { final SurfaceControl.Builder builder = super.makeSurface(); if (mRoundedCornerOverlay) { - builder.setParent(getDisplayContent().getOverlayLayer()); + builder.setParent(null); } return builder; } From 7ea6094f3b057fb1243608746c0abf561f5dd1be Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 8 Jul 2022 19:06:17 +0800 Subject: [PATCH 2/2] Fix flickering when rapidly switch resolutions - The screen decor layers are moved out from display due to a memory regression issue(b/235601833). So, the SC.captureLayers will no longer be able to include the screen decor layers. - We now use SC.captureDisplay instead for resolution chagne case. - Previously, we hide the screen decor layers while animation is running and show them back when the animation ends, but it would cause flicker if user rapidly switch resolution. Because the previous ScreenRotationAnimation.kill() can be called after creating a new ScreenRotatioAnimation, then the screen decor layers hidden by the current animation are shown unexpectedly. Example: 1. Anim1 start (hide decor layers) 2. Anim2 start (hide decor layers) 3. Anim1 end (show decor layers) -> flicker 4. Anim2 end (show decor layers) - Only re-show the screen decor layers when current animation is the last one. Bug: 237354783 Test: 1. Go Settings > Display > Screen resolution 2. Rapidly switch resolutions Change-Id: Ia42eb8538a07e49c0ddcd6d48470a1afc8caae5a --- .../com/android/server/wm/DisplayContent.java | 7 +- .../server/wm/ScreenRotationAnimation.java | 69 ++++++++++++++++--- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 72b996c4662d1..79aef00750a12 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3233,10 +3233,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) { - if (mScreenRotationAnimation != null) { - mScreenRotationAnimation.kill(); - } + final ScreenRotationAnimation prev = mScreenRotationAnimation; mScreenRotationAnimation = screenRotationAnimation; + if (prev != null) { + prev.kill(); + } // Hide the windows which are not significant in rotation animation. So that the windows // don't need to block the unfreeze time. diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index bee44def1512d..f31a3cc9bcb3e 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -40,9 +40,11 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.hardware.HardwareBuffer; +import android.os.IBinder; import android.os.Trace; import android.util.Slog; import android.util.proto.ProtoOutputStream; +import android.view.DisplayAddress; import android.view.DisplayInfo; import android.view.Surface; import android.view.Surface.OutOfResourcesException; @@ -165,18 +167,43 @@ class ScreenRotationAnimation { final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); try { - SurfaceControl.LayerCaptureArgs.Builder builder = - new SurfaceControl.LayerCaptureArgs.Builder(displayContent.getSurfaceControl()) - .setCaptureSecureLayers(true) - .setAllowProtected(true) - .setSourceCrop(new Rect(0, 0, width, height)); - + final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer; if (isSizeChanged) { + final DisplayAddress address = displayInfo.address; + if (!(address instanceof DisplayAddress.Physical)) { + Slog.e(TAG, "Display does not have a physical address: " + displayId); + return; + } + final DisplayAddress.Physical physicalAddress = + (DisplayAddress.Physical) address; + final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken( + physicalAddress.getPhysicalDisplayId()); + if (displayToken == null) { + Slog.e(TAG, "Display token is null."); + return; + } + // Temporarily not skip screenshot for the rounded corner overlays and screenshot + // the whole display to include the rounded corner overlays. + setSkipScreenshotForRoundedCornerOverlays(false, t); mRoundedCornerOverlay = displayContent.findRoundedCornerOverlays(); + final SurfaceControl.DisplayCaptureArgs captureArgs = + new SurfaceControl.DisplayCaptureArgs.Builder(displayToken) + .setSourceCrop(new Rect(0, 0, width, height)) + .setAllowProtected(true) + .setCaptureSecureLayers(true) + .build(); + screenshotBuffer = SurfaceControl.captureDisplay(captureArgs); + } else { + SurfaceControl.LayerCaptureArgs captureArgs = + new SurfaceControl.LayerCaptureArgs.Builder( + displayContent.getSurfaceControl()) + .setCaptureSecureLayers(true) + .setAllowProtected(true) + .setSourceCrop(new Rect(0, 0, width, height)) + .build(); + screenshotBuffer = SurfaceControl.captureLayers(captureArgs); } - SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = - SurfaceControl.captureLayers(builder.build()); if (screenshotBuffer == null) { Slog.w(TAG, "Unable to take screenshot of display " + displayId); return; @@ -275,6 +302,21 @@ class ScreenRotationAnimation { t.apply(); } + void setSkipScreenshotForRoundedCornerOverlays( + boolean skipScreenshot, SurfaceControl.Transaction t) { + mDisplayContent.forAllWindows(w -> { + if (!w.mToken.mRoundedCornerOverlay || !w.isVisible() || !w.mWinAnimator.hasSurface()) { + return; + } + t.setSkipScreenshot(w.mWinAnimator.mSurfaceController.mSurfaceControl, skipScreenshot); + }, false); + if (!skipScreenshot) { + // Use sync apply to apply the change immediately, so that the next + // SC.captureDisplay can capture the screen decor layers. + t.apply(true /* sync */); + } + } + public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(STARTED, mStarted); @@ -483,10 +525,15 @@ class ScreenRotationAnimation { } mBackColorSurface = null; } + if (mRoundedCornerOverlay != null) { - for (SurfaceControl sc : mRoundedCornerOverlay) { - if (sc.isValid()) { - t.show(sc); + if (mDisplayContent.getRotationAnimation() == null + || mDisplayContent.getRotationAnimation() == this) { + setSkipScreenshotForRoundedCornerOverlays(true, t); + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.show(sc); + } } } mRoundedCornerOverlay = null;