Merge "Allow polling for WindowInsets."
diff --git a/api/current.txt b/api/current.txt
index 2cdae98..c075029e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34162,6 +34162,7 @@
     method protected float getRightFadingEdgeStrength();
     method protected int getRightPaddingOffset();
     method public android.view.View getRootView();
+    method public android.view.WindowInsets getRootWindowInsets();
     method public float getRotation();
     method public float getRotationX();
     method public float getRotationY();
diff --git a/api/system-current.txt b/api/system-current.txt
index 1b3f1e4..eb47c5e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -36330,6 +36330,7 @@
     method protected float getRightFadingEdgeStrength();
     method protected int getRightPaddingOffset();
     method public android.view.View getRootView();
+    method public android.view.WindowInsets getRootWindowInsets();
     method public float getRotation();
     method public float getRotationX();
     method public float getRotationY();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 085a3f2..4f2d4a6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6564,6 +6564,19 @@
     }
 
     /**
+     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
+     * only available if the view is attached.
+     *
+     * @return WindowInsets from the top of the view hierarchy or null if View is detached
+     */
+    public WindowInsets getRootWindowInsets() {
+        if (mAttachInfo != null) {
+            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
+        }
+        return null;
+    }
+
+    /**
      * @hide Compute the insets that should be consumed by this view and the ones
      * that should propagate to those under it.
      */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7cd12d5..f970e88 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -265,6 +265,8 @@
     final Rect mDispatchContentInsets = new Rect();
     final Rect mDispatchStableInsets = new Rect();
 
+    private WindowInsets mLastWindowInsets;
+
     final Configuration mLastConfiguration = new Configuration();
     final Configuration mPendingConfiguration = new Configuration();
 
@@ -550,6 +552,11 @@
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingStableInsets.set(mAttachInfo.mStableInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
+                try {
+                    relayoutWindow(attrs, getHostVisibility(), false);
+                } catch (RemoteException e) {
+                    if (DEBUG_LAYOUT) Log.e(TAG, "failed to relayoutWindow", e);
+                }
                 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
                 if (res < WindowManagerGlobal.ADD_OKAY) {
                     mAttachInfo.mRootView = null;
@@ -1227,13 +1234,29 @@
         m.postTranslate(-mAttachInfo.mWindowLeft, -mAttachInfo.mWindowTop);
     }
 
+    /* package */ WindowInsets getWindowInsets(boolean forceConstruct) {
+        if (mLastWindowInsets == null || forceConstruct) {
+            mDispatchContentInsets.set(mAttachInfo.mContentInsets);
+            mDispatchStableInsets.set(mAttachInfo.mStableInsets);
+            Rect contentInsets = mDispatchContentInsets;
+            Rect stableInsets = mDispatchStableInsets;
+            // For dispatch we preserve old logic, but for direct requests from Views we allow to
+            // immediately use pending insets.
+            if (!forceConstruct
+                    && (!mPendingContentInsets.equals(contentInsets) ||
+                        !mPendingStableInsets.equals(stableInsets))) {
+                contentInsets = mPendingContentInsets;
+                stableInsets = mPendingStableInsets;
+            }
+            final boolean isRound = (mIsEmulator && mIsCircularEmulator) || mWindowIsRound;
+            mLastWindowInsets = new WindowInsets(contentInsets,
+                    null /* windowDecorInsets */, stableInsets, isRound);
+        }
+        return mLastWindowInsets;
+    }
+
     void dispatchApplyInsets(View host) {
-        mDispatchContentInsets.set(mAttachInfo.mContentInsets);
-        mDispatchStableInsets.set(mAttachInfo.mStableInsets);
-        final boolean isRound = (mIsEmulator && mIsCircularEmulator) || mWindowIsRound;
-        host.dispatchApplyWindowInsets(new WindowInsets(
-                mDispatchContentInsets, null /* windowDecorInsets */,
-                mDispatchStableInsets, isRound));
+        host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */));
     }
 
     private void performTraversals() {