diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java index 141849f0593a0..b74b80eeec2cf 100644 --- a/core/java/android/view/WindowMetrics.java +++ b/core/java/android/view/WindowMetrics.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.graphics.Point; import android.graphics.Rect; +import java.util.function.Supplier; + /** * Metrics about a Window, consisting of the bounds and {@link WindowInsets}. *

@@ -50,8 +52,9 @@ import android.graphics.Rect; public final class WindowMetrics { @NonNull private final Rect mBounds; - @NonNull - private final WindowInsets mWindowInsets; + + private WindowInsets mWindowInsets; + private Supplier mWindowInsetsSupplier; /** @see android.util.DisplayMetrics#density */ private final float mDensity; @@ -80,6 +83,21 @@ public final class WindowMetrics { mDensity = density; } + /** + * Similar to {@link #WindowMetrics(Rect, WindowInsets, float)} but the window insets are + * computed when {@link #getWindowInsets()} is first time called. This reduces unnecessary + * calculation and the overhead of obtaining insets state from server side because most + * callers are usually only interested in {@link #getBounds()}. + * + * @hide + */ + public WindowMetrics(@NonNull Rect bounds, @NonNull Supplier windowInsetsSupplier, + float density) { + mBounds = bounds; + mWindowInsetsSupplier = windowInsetsSupplier; + mDensity = density; + } + /** * Returns the bounds of the area associated with this window or * {@link android.annotation.UiContext}. @@ -121,7 +139,10 @@ public final class WindowMetrics { */ @NonNull public WindowInsets getWindowInsets() { - return mWindowInsets; + if (mWindowInsets != null) { + return mWindowInsets; + } + return mWindowInsets = mWindowInsetsSupplier.get(); } /** diff --git a/core/java/android/window/WindowMetricsController.java b/core/java/android/window/WindowMetricsController.java index 06449d519f689..11bd47da97745 100644 --- a/core/java/android/window/WindowMetricsController.java +++ b/core/java/android/window/WindowMetricsController.java @@ -41,6 +41,7 @@ import android.view.WindowMetrics; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.Supplier; /** * A controller to handle {@link android.view.WindowMetrics} related APIs, which are @@ -53,6 +54,9 @@ import java.util.Set; * @hide */ public final class WindowMetricsController { + // TODO(b/151908239): Remove and always enable this if it is stable. + private static final boolean LAZY_WINDOW_INSETS = android.os.SystemProperties.getBoolean( + "persist.wm.debug.win_metrics_lazy_insets", false); private final Context mContext; public WindowMetricsController(@NonNull Context context) { @@ -92,16 +96,11 @@ public final class WindowMetricsController { windowingMode = winConfig.getWindowingMode(); } final IBinder token = Context.getToken(mContext); - final WindowInsets windowInsets = getWindowInsetsFromServerForCurrentDisplay(token, - bounds, isScreenRound, windowingMode); - return new WindowMetrics(bounds, windowInsets, density); - } - - private WindowInsets getWindowInsetsFromServerForCurrentDisplay( - IBinder token, Rect bounds, boolean isScreenRound, - @WindowConfiguration.WindowingMode int windowingMode) { - return getWindowInsetsFromServerForDisplay(mContext.getDisplayId(), token, bounds, - isScreenRound, windowingMode); + final Supplier insetsSupplier = () -> getWindowInsetsFromServerForDisplay( + mContext.getDisplayId(), token, bounds, isScreenRound, windowingMode); + return LAZY_WINDOW_INSETS + ? new WindowMetrics(new Rect(bounds), insetsSupplier, density) + : new WindowMetrics(new Rect(bounds), insetsSupplier.get(), density); } /**