From a8037620bdc21436ebbd86bd06e7fbec7b8e8d32 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 13 Jan 2023 16:28:24 +0000 Subject: [PATCH] Calculate StatusBar height locally in Launcher When reading the status bar inset on devices with multiple displays after switching the displays the inset is not updated immediately (SystemUI should update the height of the window first by reacting to the display switch in it's own process). Due to this race condition Launcher is very likely to calculate DeviceProfile with incorrect inset of the previous display first and update it to the correct one only after SystemUI finished the window update. To avoid this adding calculation of the StatusBar height to Launcher locally using the same utility method that is used by SystemUI. Bug: 264656380 Test: manual test that the statusbar height is calculated correctly in Launcher on a device with two displays, both on the inner and outer display and different rotations Change-Id: Ia16ecadd8fcac29082d27ca693ab7740ce6161c4 --- .../util/SystemWindowManagerProxy.java | 8 ++++++++ .../util/window/WindowManagerProxy.java | 18 ++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java index 5dc461363b..a34888f684 100644 --- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java +++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java @@ -23,6 +23,7 @@ import android.view.Surface; import android.view.WindowManager; import android.view.WindowMetrics; +import com.android.internal.policy.SystemBarUtils; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.window.CachedDisplayInfo; import com.android.launcher3.util.window.WindowManagerProxy; @@ -44,6 +45,13 @@ public class SystemWindowManagerProxy extends WindowManagerProxy { .getRotation(); } + @Override + protected int getStatusBarHeight(Context context, boolean isPortrait, int statusBarInset) { + // See b/264656380, calculate the status bar height manually as the inset in the system + // server might not be updated by this point yet causing extra DeviceProfile updates + return SystemBarUtils.getStatusBarHeight(context); + } + @Override public ArrayMap estimateInternalDisplayBounds( Context displayInfoContext) { diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index fb2ae732b7..4093bc913d 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -161,12 +161,10 @@ public class WindowManagerProxy implements ResourceBasedOverride { insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets); Insets statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars()); - int statusBarHeight = getDimenByName(systemRes, - (isPortrait) ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE, - STATUS_BAR_HEIGHT); + Insets newStatusBarInsets = Insets.of( statusBarInsets.left, - Math.max(statusBarInsets.top, statusBarHeight), + getStatusBarHeight(context, isPortrait, statusBarInsets.top), statusBarInsets.right, statusBarInsets.bottom); insetsBuilder.setInsets(WindowInsets.Type.statusBars(), newStatusBarInsets); @@ -190,6 +188,15 @@ public class WindowManagerProxy implements ResourceBasedOverride { return result; } + protected int getStatusBarHeight(Context context, boolean isPortrait, int statusBarInset) { + Resources systemRes = context.getResources(); + int statusBarHeight = getDimenByName(systemRes, + isPortrait ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE, + STATUS_BAR_HEIGHT); + + return Math.max(statusBarInset, statusBarHeight); + } + /** * Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations */ @@ -212,6 +219,9 @@ public class WindowManagerProxy implements ResourceBasedOverride { boolean isTabletOrGesture = isTablet || (Utilities.ATLEAST_R && isGestureNav(context)); + // Use the status bar height resources because current system API to get the status bar + // height doesn't allow to do this for an arbitrary display, it returns value only + // for the current active display (see com.android.internal.policy.StatusBarUtils) int statusBarHeightPortrait = getDimenByName(systemRes, STATUS_BAR_HEIGHT_PORTRAIT, STATUS_BAR_HEIGHT); int statusBarHeightLandscape = getDimenByName(systemRes,