Merge "Add lazy evaluation for getWindowInsets()"
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
index 141849f..b74b80e 100644
--- a/core/java/android/view/WindowMetrics.java
+++ b/core/java/android/view/WindowMetrics.java
@@ -20,6 +20,8 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 
+import java.util.function.Supplier;
+
 /**
  * Metrics about a Window, consisting of the bounds and {@link WindowInsets}.
  * <p>
@@ -50,8 +52,9 @@
 public final class WindowMetrics {
     @NonNull
     private final Rect mBounds;
-    @NonNull
-    private final WindowInsets mWindowInsets;
+
+    private WindowInsets mWindowInsets;
+    private Supplier<WindowInsets> mWindowInsetsSupplier;
 
     /** @see android.util.DisplayMetrics#density */
     private final float mDensity;
@@ -81,6 +84,21 @@
     }
 
     /**
+     * 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<WindowInsets> windowInsetsSupplier,
+            float density) {
+        mBounds = bounds;
+        mWindowInsetsSupplier = windowInsetsSupplier;
+        mDensity = density;
+    }
+
+    /**
      * Returns the bounds of the area associated with this window or
      * {@link android.annotation.UiContext}.
      * <p>
@@ -121,7 +139,10 @@
      */
     @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 06449d5..11bd47d 100644
--- a/core/java/android/window/WindowMetricsController.java
+++ b/core/java/android/window/WindowMetricsController.java
@@ -41,6 +41,7 @@
 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 @@
  * @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 @@
             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<WindowInsets> 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);
     }
 
     /**