Fix flicker when swiching resolution change

After the "Local Layout"[1] is enabled, the client can compute its
layout on its own. If we update cutout in the Display callback(server
side), it would have a timing issue that we draw the cutout(latest from
server) in the old layout(not being updated yet in client) which would
cause flicker.

We should only update cutout in client side callback like configuration
change to make sure it syncs with the current layout attributes in
client side.

For rounded corner part, we don't need to reload drawable everytime the
config is changed. Only size update is needed.

[1]:If9488ffc84dc5e2af106acfae425a854fb7407a2

Bug: 228284551
Bug: 244693677
Test: 1. Go Settings-> Display-> Screen resolution
      2. Switch between FHD <-> QHD and no flickering
Test: atest ScreenDecorationsTest RoundedCornerResDelegateTest
Change-Id: Idd45af5aa2b9419eb91994eb2071e5be616204b7
This commit is contained in:
Shawn Lin
2022-09-07 18:19:33 +08:00
parent 1d073c9600
commit 808e22eac1
4 changed files with 15 additions and 104 deletions

View File

@@ -455,7 +455,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
boolean needToUpdateProviderViews = false;
final String newUniqueId = mDisplayInfo.uniqueId;
if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
mDisplayUniqueId = newUniqueId;
@@ -473,37 +472,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
setupDecorations();
return;
}
if (mScreenDecorHwcLayer != null) {
updateHwLayerRoundedCornerDrawable();
updateHwLayerRoundedCornerExistAndSize();
}
needToUpdateProviderViews = true;
}
final float newRatio = getPhysicalPixelDisplaySizeRatio();
if (mRoundedCornerResDelegate.getPhysicalPixelDisplaySizeRatio() != newRatio) {
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(newRatio);
if (mScreenDecorHwcLayer != null) {
updateHwLayerRoundedCornerExistAndSize();
}
needToUpdateProviderViews = true;
}
if (needToUpdateProviderViews) {
updateOverlayProviderViews(null);
} else {
updateOverlayProviderViews(new Integer[] {
mFaceScanningViewId,
R.id.display_cutout,
R.id.display_cutout_left,
R.id.display_cutout_right,
R.id.display_cutout_bottom,
});
}
if (mScreenDecorHwcLayer != null) {
mScreenDecorHwcLayer.onDisplayChanged(newUniqueId);
}
}
};
@@ -1069,6 +1037,8 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
&& (newRotation != mRotation || displayModeChanged(mDisplayMode, newMod))) {
mRotation = newRotation;
mDisplayMode = newMod;
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
getPhysicalPixelDisplaySizeRatio());
if (mScreenDecorHwcLayer != null) {
mScreenDecorHwcLayer.pendingConfigChange = false;
mScreenDecorHwcLayer.updateRotation(mRotation);

View File

@@ -78,23 +78,18 @@ class RoundedCornerResDelegate(
reloadMeasures()
}
private fun reloadAll(newReloadToken: Int) {
if (reloadToken == newReloadToken) {
return
}
reloadToken = newReloadToken
reloadRes()
reloadMeasures()
}
fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
if (displayUniqueId != newDisplayUniqueId) {
displayUniqueId = newDisplayUniqueId
newReloadToken ?.let { reloadToken = it }
reloadRes()
reloadMeasures()
} else {
newReloadToken?.let { reloadAll(it) }
} else if (newReloadToken != null) {
if (reloadToken == newReloadToken) {
return
}
reloadToken = newReloadToken
reloadMeasures()
}
}

View File

@@ -1005,18 +1005,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
assertEquals(new Size(3, 3), resDelegate.getTopRoundedSize());
assertEquals(new Size(4, 4), resDelegate.getBottomRoundedSize());
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
doReturn(2f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
mDisplayInfo.rotation = Surface.ROTATION_270;
mScreenDecorations.onConfigurationChanged(null);
assertEquals(new Size(4, 4), resDelegate.getTopRoundedSize());
assertEquals(new Size(5, 5), resDelegate.getBottomRoundedSize());
assertEquals(new Size(6, 6), resDelegate.getTopRoundedSize());
assertEquals(new Size(8, 8), resDelegate.getBottomRoundedSize());
}
@Test
@@ -1292,51 +1287,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verifyFaceScanningViewExists(true);
}
@Test
public void testOnDisplayChanged_hwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
final ScreenDecorHwcLayer hwcLayer = mScreenDecorations.mScreenDecorHwcLayer;
spyOn(hwcLayer);
doReturn(mDisplay).when(hwcLayer).getDisplay();
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
verify(hwcLayer, times(1)).onDisplayChanged(any());
}
@Test
public void testOnDisplayChanged_nonHwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
final ScreenDecorations.DisplayCutoutView cutoutView = (ScreenDecorations.DisplayCutoutView)
mScreenDecorations.getOverlayView(R.id.display_cutout);
assertNotNull(cutoutView);
spyOn(cutoutView);
doReturn(mDisplay).when(cutoutView).getDisplay();
mScreenDecorations.mDisplayListener.onDisplayChanged(1);
verify(cutoutView, times(1)).onDisplayChanged(any());
}
@Test
public void testHasSameProvidersWithNullOverlays() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,

View File

@@ -24,12 +24,11 @@ import androidx.annotation.DrawableRes
import androidx.test.filters.SmallTest
import com.android.internal.R as InternalR
import com.android.systemui.R as SystemUIR
import com.android.systemui.tests.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.tests.R
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@@ -102,14 +101,11 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize)
setupResources(radius = 100,
roundedTopDrawable = getTestsDrawable(R.drawable.rounded4px),
roundedBottomDrawable = getTestsDrawable(R.drawable.rounded5px))
roundedCornerResDelegate.physicalPixelDisplaySizeRatio = 2f
roundedCornerResDelegate.updateDisplayUniqueId(null, 1)
assertEquals(Size(4, 4), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
assertEquals(Size(8, 8), roundedCornerResDelegate.bottomRoundedSize)
}
@Test