Merge "Fix cutout flicker while switch screen resolution" into tm-dev am: 842704d45a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18283848 Change-Id: If3cfedc1b10402ad2dd4eb610c5944f304d579fe Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -54,7 +54,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
||||||
@JvmField val displayInfo = DisplayInfo()
|
@JvmField val displayInfo = DisplayInfo()
|
||||||
@JvmField protected var pendingRotationChange = false
|
@JvmField protected var pendingConfigChange = false
|
||||||
@JvmField protected val paint = Paint()
|
@JvmField protected val paint = Paint()
|
||||||
@JvmField protected val cutoutPath = Path()
|
@JvmField protected val cutoutPath = Path()
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
||||||
open fun updateCutout() {
|
open fun updateCutout() {
|
||||||
if (pendingRotationChange) {
|
if (pendingConfigChange) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cutoutPath.reset()
|
cutoutPath.reset()
|
||||||
@@ -225,7 +225,7 @@ open class DisplayCutoutBaseView : View, RegionInterceptableView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun updateProtectionBoundingPath() {
|
protected open fun updateProtectionBoundingPath() {
|
||||||
if (pendingRotationChange) {
|
if (pendingConfigChange) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val m = Matrix()
|
val m = Matrix()
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import android.provider.Settings.Secure;
|
|||||||
import android.util.DisplayUtils;
|
import android.util.DisplayUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.DisplayCutout;
|
import android.view.DisplayCutout;
|
||||||
import android.view.DisplayCutout.BoundsPosition;
|
import android.view.DisplayCutout.BoundsPosition;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
@@ -151,12 +152,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
private SettingObserver mColorInversionSetting;
|
private SettingObserver mColorInversionSetting;
|
||||||
private DelayableExecutor mExecutor;
|
private DelayableExecutor mExecutor;
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
boolean mPendingRotationChange;
|
boolean mPendingConfigChange;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
String mDisplayUniqueId;
|
String mDisplayUniqueId;
|
||||||
private int mTintColor = Color.BLACK;
|
private int mTintColor = Color.BLACK;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected DisplayDecorationSupport mHwcScreenDecorationSupport;
|
protected DisplayDecorationSupport mHwcScreenDecorationSupport;
|
||||||
|
private Display.Mode mDisplayMode;
|
||||||
|
|
||||||
private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback =
|
private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback =
|
||||||
new CameraAvailabilityListener.CameraTransitionCallback() {
|
new CameraAvailabilityListener.CameraTransitionCallback() {
|
||||||
@@ -324,6 +326,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||||
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
||||||
mRotation = mContext.getDisplay().getRotation();
|
mRotation = mContext.getDisplay().getRotation();
|
||||||
|
mDisplayMode = mContext.getDisplay().getMode();
|
||||||
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
|
mDisplayUniqueId = mContext.getDisplay().getUniqueId();
|
||||||
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
|
mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
|
||||||
mDisplayUniqueId);
|
mDisplayUniqueId);
|
||||||
@@ -349,8 +352,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
@Override
|
@Override
|
||||||
public void onDisplayChanged(int displayId) {
|
public void onDisplayChanged(int displayId) {
|
||||||
final int newRotation = mContext.getDisplay().getRotation();
|
final int newRotation = mContext.getDisplay().getRotation();
|
||||||
|
final Display.Mode newDisplayMode = mContext.getDisplay().getMode();
|
||||||
if ((mOverlays != null || mScreenDecorHwcWindow != null)
|
if ((mOverlays != null || mScreenDecorHwcWindow != null)
|
||||||
&& mRotation != newRotation) {
|
&& (mRotation != newRotation
|
||||||
|
|| displayModeChanged(mDisplayMode, newDisplayMode))) {
|
||||||
// We cannot immediately update the orientation. Otherwise
|
// We cannot immediately update the orientation. Otherwise
|
||||||
// WindowManager is still deferring layout until it has finished dispatching
|
// WindowManager is still deferring layout until it has finished dispatching
|
||||||
// the config changes, which may cause divergence between what we draw
|
// the config changes, which may cause divergence between what we draw
|
||||||
@@ -358,10 +363,16 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
// Instead we wait until either:
|
// Instead we wait until either:
|
||||||
// - we are trying to redraw. This because WM resized our window and told us to.
|
// - we are trying to redraw. This because WM resized our window and told us to.
|
||||||
// - the config change has been dispatched, so WM is no longer deferring layout.
|
// - the config change has been dispatched, so WM is no longer deferring layout.
|
||||||
mPendingRotationChange = true;
|
mPendingConfigChange = true;
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.i(TAG, "Rotation changed, deferring " + newRotation + ", staying at "
|
if (mRotation != newRotation) {
|
||||||
+ mRotation);
|
Log.i(TAG, "Rotation changed, deferring " + newRotation
|
||||||
|
+ ", staying at " + mRotation);
|
||||||
|
}
|
||||||
|
if (displayModeChanged(mDisplayMode, newDisplayMode)) {
|
||||||
|
Log.i(TAG, "Resolution changed, deferring " + newDisplayMode
|
||||||
|
+ ", staying at " + mDisplayMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mOverlays != null) {
|
if (mOverlays != null) {
|
||||||
@@ -369,7 +380,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
if (mOverlays[i] != null) {
|
if (mOverlays[i] != null) {
|
||||||
final ViewGroup overlayView = mOverlays[i].getRootView();
|
final ViewGroup overlayView = mOverlays[i].getRootView();
|
||||||
overlayView.getViewTreeObserver().addOnPreDrawListener(
|
overlayView.getViewTreeObserver().addOnPreDrawListener(
|
||||||
new RestartingPreDrawListener(overlayView, i, newRotation));
|
new RestartingPreDrawListener(
|
||||||
|
overlayView, i, newRotation, newDisplayMode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +391,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
new RestartingPreDrawListener(
|
new RestartingPreDrawListener(
|
||||||
mScreenDecorHwcWindow,
|
mScreenDecorHwcWindow,
|
||||||
-1, // Pass -1 for views with no specific position.
|
-1, // Pass -1 for views with no specific position.
|
||||||
newRotation));
|
newRotation, newDisplayMode));
|
||||||
|
}
|
||||||
|
if (mScreenDecorHwcLayer != null) {
|
||||||
|
mScreenDecorHwcLayer.pendingConfigChange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +450,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
};
|
};
|
||||||
|
|
||||||
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
|
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
|
||||||
updateOrientation();
|
updateConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -807,6 +822,17 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean displayModeChanged(Display.Mode oldMode, Display.Mode newMode) {
|
||||||
|
if (oldMode == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We purposely ignore refresh rate and id changes here, because we don't need to
|
||||||
|
// invalidate for those, and they can trigger the refresh rate to increase
|
||||||
|
return oldMode.getPhysicalWidth() != newMode.getPhysicalWidth()
|
||||||
|
|| oldMode.getPhysicalHeight() != newMode.getPhysicalHeight();
|
||||||
|
}
|
||||||
|
|
||||||
private int getOverlayWindowGravity(@BoundsPosition int pos) {
|
private int getOverlayWindowGravity(@BoundsPosition int pos) {
|
||||||
final int rotated = getBoundPositionFromRotation(pos, mRotation);
|
final int rotated = getBoundPositionFromRotation(pos, mRotation);
|
||||||
switch (rotated) {
|
switch (rotated) {
|
||||||
@@ -913,8 +939,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
|
|
||||||
mExecutor.execute(() -> {
|
mExecutor.execute(() -> {
|
||||||
int oldRotation = mRotation;
|
int oldRotation = mRotation;
|
||||||
mPendingRotationChange = false;
|
mPendingConfigChange = false;
|
||||||
updateOrientation();
|
updateConfiguration();
|
||||||
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
|
if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
|
||||||
setupDecorations();
|
setupDecorations();
|
||||||
if (mOverlays != null) {
|
if (mOverlays != null) {
|
||||||
@@ -941,7 +967,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
pw.println(" DEBUG_DISABLE_SCREEN_DECORATIONS:" + DEBUG_DISABLE_SCREEN_DECORATIONS);
|
pw.println(" DEBUG_DISABLE_SCREEN_DECORATIONS:" + DEBUG_DISABLE_SCREEN_DECORATIONS);
|
||||||
pw.println(" mIsPrivacyDotEnabled:" + isPrivacyDotEnabled());
|
pw.println(" mIsPrivacyDotEnabled:" + isPrivacyDotEnabled());
|
||||||
pw.println(" isOnlyPrivacyDotInSwLayer:" + isOnlyPrivacyDotInSwLayer());
|
pw.println(" isOnlyPrivacyDotInSwLayer:" + isOnlyPrivacyDotInSwLayer());
|
||||||
pw.println(" mPendingRotationChange:" + mPendingRotationChange);
|
pw.println(" mPendingConfigChange:" + mPendingConfigChange);
|
||||||
if (mHwcScreenDecorationSupport != null) {
|
if (mHwcScreenDecorationSupport != null) {
|
||||||
pw.println(" mHwcScreenDecorationSupport:");
|
pw.println(" mHwcScreenDecorationSupport:");
|
||||||
pw.println(" format="
|
pw.println(" format="
|
||||||
@@ -973,7 +999,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
mRoundedCornerResDelegate.dump(pw, args);
|
mRoundedCornerResDelegate.dump(pw, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOrientation() {
|
private void updateConfiguration() {
|
||||||
Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
|
Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
|
||||||
"must call on " + mHandler.getLooper().getThread()
|
"must call on " + mHandler.getLooper().getThread()
|
||||||
+ ", but was " + Thread.currentThread());
|
+ ", but was " + Thread.currentThread());
|
||||||
@@ -982,11 +1008,14 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
if (mRotation != newRotation) {
|
if (mRotation != newRotation) {
|
||||||
mDotViewController.setNewRotation(newRotation);
|
mDotViewController.setNewRotation(newRotation);
|
||||||
}
|
}
|
||||||
|
final Display.Mode newMod = mContext.getDisplay().getMode();
|
||||||
|
|
||||||
if (!mPendingRotationChange && newRotation != mRotation) {
|
if (!mPendingConfigChange
|
||||||
|
&& (newRotation != mRotation || displayModeChanged(mDisplayMode, newMod))) {
|
||||||
mRotation = newRotation;
|
mRotation = newRotation;
|
||||||
|
mDisplayMode = newMod;
|
||||||
if (mScreenDecorHwcLayer != null) {
|
if (mScreenDecorHwcLayer != null) {
|
||||||
mScreenDecorHwcLayer.pendingRotationChange = false;
|
mScreenDecorHwcLayer.pendingConfigChange = false;
|
||||||
mScreenDecorHwcLayer.updateRotation(mRotation);
|
mScreenDecorHwcLayer.updateRotation(mRotation);
|
||||||
updateHwLayerRoundedCornerExistAndSize();
|
updateHwLayerRoundedCornerExistAndSize();
|
||||||
updateHwLayerRoundedCornerDrawable();
|
updateHwLayerRoundedCornerDrawable();
|
||||||
@@ -1197,7 +1226,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
||||||
@Override
|
@Override
|
||||||
public void updateCutout() {
|
public void updateCutout() {
|
||||||
if (!isAttachedToWindow() || pendingRotationChange) {
|
if (!isAttachedToWindow() || pendingConfigChange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mPosition = getBoundPositionFromRotation(mInitialPosition, mRotation);
|
mPosition = getBoundPositionFromRotation(mInitialPosition, mRotation);
|
||||||
@@ -1338,40 +1367,47 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
|
|
||||||
private final View mView;
|
private final View mView;
|
||||||
private final int mTargetRotation;
|
private final int mTargetRotation;
|
||||||
|
private final Display.Mode mTargetDisplayMode;
|
||||||
// Pass -1 for ScreenDecorHwcLayer since it's a fullscreen window and has no specific
|
// Pass -1 for ScreenDecorHwcLayer since it's a fullscreen window and has no specific
|
||||||
// position.
|
// position.
|
||||||
private final int mPosition;
|
private final int mPosition;
|
||||||
|
|
||||||
private RestartingPreDrawListener(View view, @BoundsPosition int position,
|
private RestartingPreDrawListener(View view, @BoundsPosition int position,
|
||||||
int targetRotation) {
|
int targetRotation, Display.Mode targetDisplayMode) {
|
||||||
mView = view;
|
mView = view;
|
||||||
mTargetRotation = targetRotation;
|
mTargetRotation = targetRotation;
|
||||||
|
mTargetDisplayMode = targetDisplayMode;
|
||||||
mPosition = position;
|
mPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreDraw() {
|
public boolean onPreDraw() {
|
||||||
mView.getViewTreeObserver().removeOnPreDrawListener(this);
|
mView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||||
|
if (mTargetRotation == mRotation
|
||||||
if (mTargetRotation == mRotation) {
|
&& !displayModeChanged(mDisplayMode, mTargetDisplayMode)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
final String title = mPosition < 0 ? "ScreenDecorHwcLayer"
|
final String title = mPosition < 0 ? "ScreenDecorHwcLayer"
|
||||||
: getWindowTitleByPos(mPosition);
|
: getWindowTitleByPos(mPosition);
|
||||||
Log.i(TAG, title + " already in target rot "
|
Log.i(TAG, title + " already in target rot "
|
||||||
+ mTargetRotation + ", allow draw without restarting it");
|
+ mTargetRotation + " and in target resolution "
|
||||||
|
+ mTargetDisplayMode.getPhysicalWidth() + "x"
|
||||||
|
+ mTargetDisplayMode.getPhysicalHeight()
|
||||||
|
+ ", allow draw without restarting it");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPendingRotationChange = false;
|
mPendingConfigChange = false;
|
||||||
// This changes the window attributes - we need to restart the traversal for them to
|
// This changes the window attributes - we need to restart the traversal for them to
|
||||||
// take effect.
|
// take effect.
|
||||||
updateOrientation();
|
updateConfiguration();
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
final String title = mPosition < 0 ? "ScreenDecorHwcLayer"
|
final String title = mPosition < 0 ? "ScreenDecorHwcLayer"
|
||||||
: getWindowTitleByPos(mPosition);
|
: getWindowTitleByPos(mPosition);
|
||||||
Log.i(TAG, title
|
Log.i(TAG, title
|
||||||
+ " restarting listener fired, restarting draw for rot " + mRotation);
|
+ " restarting listener fired, restarting draw for rot " + mRotation
|
||||||
|
+ ", resolution " + mDisplayMode.getPhysicalWidth() + "x"
|
||||||
|
+ mDisplayMode.getPhysicalHeight());
|
||||||
}
|
}
|
||||||
mView.invalidate();
|
mView.invalidate();
|
||||||
return false;
|
return false;
|
||||||
@@ -1379,8 +1415,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pre-draw listener, that validates that the rotation we draw in matches the displays
|
* A pre-draw listener, that validates that the rotation and display resolution we draw in
|
||||||
* rotation before continuing the draw.
|
* matches the display's rotation and resolution before continuing the draw.
|
||||||
*
|
*
|
||||||
* This is to prevent a race condition, where we have not received the display changed event
|
* This is to prevent a race condition, where we have not received the display changed event
|
||||||
* yet, and would thus draw in an old orientation.
|
* yet, and would thus draw in an old orientation.
|
||||||
@@ -1396,11 +1432,21 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreDraw() {
|
public boolean onPreDraw() {
|
||||||
final int displayRotation = mContext.getDisplay().getRotation();
|
final int displayRotation = mContext.getDisplay().getRotation();
|
||||||
if (displayRotation != mRotation && !mPendingRotationChange) {
|
final Display.Mode displayMode = mContext.getDisplay().getMode();
|
||||||
|
if (displayRotation != mRotation && displayModeChanged(mDisplayMode, displayMode)
|
||||||
|
&& !mPendingConfigChange) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
if (displayRotation != mRotation) {
|
||||||
Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot "
|
Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot "
|
||||||
+ displayRotation + ". Restarting draw");
|
+ displayRotation + ". Restarting draw");
|
||||||
}
|
}
|
||||||
|
if (displayModeChanged(mDisplayMode, displayMode)) {
|
||||||
|
Log.i(TAG, "Drawing at " + mDisplayMode.getPhysicalWidth()
|
||||||
|
+ "x" + mDisplayMode.getPhysicalHeight() + ", but display is at "
|
||||||
|
+ displayMode.getPhysicalWidth() + "x"
|
||||||
|
+ displayMode.getPhysicalHeight() + ". Restarting draw");
|
||||||
|
}
|
||||||
|
}
|
||||||
mView.invalidate();
|
mView.invalidate();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
|||||||
when(mContext.getDisplay()).thenReturn(mDisplay);
|
when(mContext.getDisplay()).thenReturn(mDisplay);
|
||||||
// Not support hwc layer by default
|
// Not support hwc layer by default
|
||||||
doReturn(null).when(mDisplay).getDisplayDecorationSupport();
|
doReturn(null).when(mDisplay).getDisplayDecorationSupport();
|
||||||
|
doReturn(mDisplayMode).when(mDisplay).getMode();
|
||||||
|
|
||||||
when(mMockTypedArray.length()).thenReturn(0);
|
when(mMockTypedArray.length()).thenReturn(0);
|
||||||
mPrivacyDotTopLeftDecorProvider = spy(new PrivacyDotCornerDecorProviderImpl(
|
mPrivacyDotTopLeftDecorProvider = spy(new PrivacyDotCornerDecorProviderImpl(
|
||||||
|
|||||||
Reference in New Issue
Block a user