From 069ff5c01cbca25c332767077d95b708753e7bae Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 27 May 2022 17:02:42 +0800 Subject: [PATCH] Fixed screendecorations flickering while resolution change If the ScreenRotationAnimation is caused by resolution change: 1. Include screen decor layers in the screenshot of the ScreenRotationAnimation. 2. Hide the screen decor layers while the animation is running and resotre back to visible when the animation ends. Bug:228284551 Test: 1. go Settings > Display > Screen resolution 2. swithc between FHD & QHD and no flickering Change-Id: Ib6be8e1ce5a99163625e0276c7c3c164a35d420f --- .../com/android/server/wm/DisplayContent.java | 2 +- .../server/wm/ScreenRotationAnimation.java | 48 ++++++++++++++----- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 98c5d512be0e6..4b3729de25358 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5395,7 +5395,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp SurfaceControl[] findRoundedCornerOverlays() { List roundedCornerOverlays = new ArrayList<>(); for (WindowToken token : mTokenMap.values()) { - if (token.mRoundedCornerOverlay) { + if (token.mRoundedCornerOverlay && token.isVisible()) { roundedCornerOverlays.add(token.mSurfaceControl); } } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 2ef19321d9583..f80e732c8212a 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -102,6 +102,7 @@ class ScreenRotationAnimation { private SurfaceControl mEnterBlackFrameLayer; /** This layer contains the actual screenshot that is to be faded out. */ private SurfaceControl mScreenshotLayer; + private SurfaceControl[] mRoundedCornerOverlay; /** * Only used for screen rotation and not custom animations. Layered behind all other layers * to avoid showing any "empty" spots @@ -151,6 +152,11 @@ class ScreenRotationAnimation { final boolean flipped = delta == Surface.ROTATION_90 || delta == Surface.ROTATION_270; mOriginalWidth = flipped ? height : width; mOriginalHeight = flipped ? width : height; + final int logicalWidth = displayInfo.logicalWidth; + final int logicalHeight = displayInfo.logicalHeight; + final boolean isSizeChanged = + logicalWidth > mOriginalWidth == logicalHeight > mOriginalHeight + && (logicalWidth != mOriginalWidth || logicalHeight != mOriginalHeight); mSurfaceRotationAnimationController = new SurfaceRotationAnimationController(); // Check whether the current screen contains any secure content. @@ -159,18 +165,23 @@ class ScreenRotationAnimation { final SurfaceControl.Transaction t = mService.mTransactionFactory.get(); try { - SurfaceControl.LayerCaptureArgs args = + SurfaceControl.LayerCaptureArgs.Builder builder = new SurfaceControl.LayerCaptureArgs.Builder(displayContent.getSurfaceControl()) .setCaptureSecureLayers(true) .setAllowProtected(true) - .setSourceCrop(new Rect(0, 0, width, height)) - // Exclude rounded corner overlay from screenshot buffer. Rounded - // corner overlay windows are un-rotated during rotation animation - // for a seamless transition. - .setExcludeLayers(displayContent.findRoundedCornerOverlays()) - .build(); + .setSourceCrop(new Rect(0, 0, width, height)); + + 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 = - SurfaceControl.captureLayers(args); + SurfaceControl.captureLayers(builder.build()); if (screenshotBuffer == null) { Slog.w(TAG, "Unable to take screenshot of display " + displayId); return; @@ -232,6 +243,14 @@ class ScreenRotationAnimation { t.show(mScreenshotLayer); t.show(mBackColorSurface); + if (mRoundedCornerOverlay != null) { + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.hide(sc); + } + } + } + } catch (OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate freeze surface", e); } @@ -240,10 +259,7 @@ class ScreenRotationAnimation { // the new logical display size. Currently pending transaction and RWC#mDisplayTransaction // are merged to global transaction, so it can be synced with display change when calling // DisplayManagerInternal#performTraversal(transaction). - final int logicalWidth = displayInfo.logicalWidth; - final int logicalHeight = displayInfo.logicalHeight; - if (logicalWidth > mOriginalWidth == logicalHeight > mOriginalHeight - && (logicalWidth != mOriginalWidth || logicalHeight != mOriginalHeight)) { + if (mScreenshotLayer != null && isSizeChanged) { displayContent.getPendingTransaction().setGeometry(mScreenshotLayer, new Rect(0, 0, mOriginalWidth, mOriginalHeight), new Rect(0, 0, logicalWidth, logicalHeight), Surface.ROTATION_0); @@ -472,6 +488,14 @@ class ScreenRotationAnimation { } mBackColorSurface = null; } + if (mRoundedCornerOverlay != null) { + for (SurfaceControl sc : mRoundedCornerOverlay) { + if (sc.isValid()) { + t.show(sc); + } + } + mRoundedCornerOverlay = null; + } t.apply(); }