Update config according to insets of status bar

Previously, only cutout and navbar are included, so only the change
of decor frame may trigger config change.
But screenWidthDp and screenHeightDp are calculated according to
config (stable) frame, which includes the insets from status bar.

So this change makes the display configuration consistent with the
latest state of the display decor insets.

Also includes Ieedcc6388237b7feccd8a869105a5f8e70ff4afd to ensure
insets in non-current rotation are updated.

Fix: 259693044
Test: DisplayPolicyTests#testUpdateDisplayConfigurationByDecor

Merged-In: Idaa7280ed23076b3282c987a249259e0c38b6630
Change-Id: Idaa7280ed23076b3282c987a249259e0c38b6630
(cherry picked from commit e3d243d3e7)
This commit is contained in:
Riddle Hsu
2023-04-25 12:28:05 +00:00
parent 0ba161ace6
commit 494547431f
6 changed files with 52 additions and 10 deletions

View File

@@ -2004,6 +2004,9 @@ public class DisplayPolicy {
*/
final Rect mConfigFrame = new Rect();
/** The count of insets sources when calculating this info. */
int mLastInsetsSourceCount;
private boolean mNeedUpdate = true;
void update(DisplayContent dc, int rotation, int w, int h) {
@@ -2025,6 +2028,7 @@ public class DisplayPolicy {
mNonDecorFrame.inset(mNonDecorInsets);
mConfigFrame.set(displayFrame);
mConfigFrame.inset(mConfigInsets);
mLastInsetsSourceCount = dc.getDisplayPolicy().mInsetsSourceWindowsExceptIme.size();
mNeedUpdate = false;
}
@@ -2033,6 +2037,7 @@ public class DisplayPolicy {
mConfigInsets.set(other.mConfigInsets);
mNonDecorFrame.set(other.mNonDecorFrame);
mConfigFrame.set(other.mConfigFrame);
mLastInsetsSourceCount = other.mLastInsetsSourceCount;
mNeedUpdate = false;
}
@@ -2048,6 +2053,12 @@ public class DisplayPolicy {
static final int DECOR_TYPES = Type.displayCutout() | Type.navigationBars();
/**
* The types that may affect display configuration. This excludes cutout because it is
* known from display info.
*/
static final int CONFIG_TYPES = Type.statusBars() | Type.navigationBars();
private final DisplayContent mDisplayContent;
private final Info[] mInfoForRotation = new Info[4];
final Info mTmpInfo = new Info();
@@ -2087,7 +2098,20 @@ public class DisplayPolicy {
final DecorInsets.Info newInfo = mDecorInsets.mTmpInfo;
newInfo.update(mDisplayContent, rotation, dw, dh);
final DecorInsets.Info currentInfo = getDecorInsetsInfo(rotation, dw, dh);
if (newInfo.mNonDecorFrame.equals(currentInfo.mNonDecorFrame)) {
if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
// Even if the config frame is not changed in current rotation, it may change the
// insets in other rotations if the source count is changed.
if (newInfo.mLastInsetsSourceCount != currentInfo.mLastInsetsSourceCount) {
for (int i = mDecorInsets.mInfoForRotation.length - 1; i >= 0; i--) {
if (i != rotation) {
final boolean flipSize = (i + rotation) % 2 == 1;
final int w = flipSize ? dh : dw;
final int h = flipSize ? dw : dh;
mDecorInsets.mInfoForRotation[i].update(mDisplayContent, i, w, h);
}
}
mDecorInsets.mInfoForRotation[rotation].set(newInfo);
}
return false;
}
mDecorInsets.invalidate();

View File

@@ -1885,7 +1885,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean needToSendNewConfiguration =
win.isVisibleRequestedOrAdding() && displayContent.updateOrientation();
if (win.providesNonDecorInsets()) {
if (win.providesDisplayDecorInsets()) {
needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo();
}
if (needToSendNewConfiguration) {
@@ -2358,7 +2358,7 @@ public class WindowManagerService extends IWindowManager.Stub
& WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
win.mLayoutNeeded = true;
}
if (layoutChanged && win.providesNonDecorInsets()) {
if (layoutChanged && win.providesDisplayDecorInsets()) {
configChanged = displayPolicy.updateDecorInsetsInfo();
}
if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0

View File

@@ -1897,13 +1897,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL;
}
boolean providesNonDecorInsets() {
boolean providesDisplayDecorInsets() {
if (mProvidedInsetsSources == null) {
return false;
}
for (int i = mProvidedInsetsSources.size() - 1; i >= 0; i--) {
final int type = mProvidedInsetsSources.keyAt(i);
if ((InsetsState.toPublicType(type) & WindowInsets.Type.navigationBars()) != 0) {
if ((InsetsState.toPublicType(type) & DisplayPolicy.DecorInsets.CONFIG_TYPES) != 0) {
return true;
}
}
@@ -2631,13 +2631,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
// Check if window provides non decor insets before clearing its provided insets.
final boolean windowProvidesNonDecorInsets = providesNonDecorInsets();
final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
removeImmediately();
// Removing a visible window may affect the display orientation so just update it if
// needed. Also recompute configuration if it provides screen decor insets.
boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation();
if (windowProvidesNonDecorInsets) {
if (windowProvidesDisplayDecorInsets) {
needToSendNewConfiguration |=
displayContent.getDisplayPolicy().updateDecorInsetsInfo();
}

View File

@@ -3117,7 +3117,7 @@ public class ActivityRecordTests extends WindowTestsBase {
.setSystemDecorations(true).build();
// Add a decor insets provider window.
final WindowState navbar = createNavBarWithProvidedInsets(squareDisplay);
assertTrue(navbar.providesNonDecorInsets()
assertTrue(navbar.providesDisplayDecorInsets()
&& squareDisplay.getDisplayPolicy().updateDecorInsetsInfo());
squareDisplay.sendNewConfiguration();
final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build();

View File

@@ -48,6 +48,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -301,20 +302,27 @@ public class DisplayPolicyTests extends WindowTestsBase {
@Test
public void testUpdateDisplayConfigurationByDecor() {
doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
final WindowState navbar = createNavBarWithProvidedInsets(mDisplayContent);
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
final DisplayInfo di = mDisplayContent.getDisplayInfo();
final int prevScreenHeightDp = mDisplayContent.getConfiguration().screenHeightDp;
assertTrue(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo());
assertTrue(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
assertEquals(NAV_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
di.logicalWidth, di.logicalHeight).mConfigInsets.bottom);
mDisplayContent.sendNewConfiguration();
assertNotEquals(prevScreenHeightDp, mDisplayContent.getConfiguration().screenHeightDp);
assertFalse(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo());
assertFalse(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
navbar.removeIfPossible();
assertEquals(0, displayPolicy.getDecorInsetsInfo(di.rotation, di.logicalWidth,
di.logicalHeight).mNonDecorInsets.bottom);
final WindowState statusBar = createStatusBarWithProvidedInsets(mDisplayContent);
assertTrue(statusBar.providesDisplayDecorInsets()
&& displayPolicy.updateDecorInsetsInfo());
assertEquals(STATUS_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
di.logicalWidth, di.logicalHeight).mConfigInsets.top);
}
@UseTestDisplay(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })

View File

@@ -438,6 +438,16 @@ class WindowTestsBase extends SystemServiceTestsBase {
return navbar;
}
WindowState createStatusBarWithProvidedInsets(DisplayContent dc) {
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, dc, "statusBar");
statusBar.mAttrs.width = WindowManager.LayoutParams.MATCH_PARENT;
statusBar.mAttrs.height = STATUS_BAR_HEIGHT;
statusBar.mAttrs.gravity = Gravity.TOP;
statusBar.mAttrs.setFitInsetsTypes(0);
dc.getDisplayPolicy().addWindowLw(statusBar, statusBar.mAttrs);
return statusBar;
}
WindowState createAppWindow(Task task, int type, String name) {
final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent());
task.addChild(activity, 0);