Make the requested visibility always up-to-date

The new logic sends the requested visibility to server even when the
client doesn't have a control. This makes the requested visibility
reliable at the server side.

This CL also changes getRequestedState to getRequestedVisibility in
WindowState, because the frames in getRequestedState are not reliable.

Fix: 161247175
Fix: 166819574
Test: atest DisplayPolicyLayoutTests DisplayPolicyTests InsetsPolicyTest
            InsetsSourceProviderTest InsetsStateControllerTest
            WindowStateTests InsetsAnimationControlImplTest
            InsetsControllerTest WindowAddRemovePerfTest
            ActivityRecordTests
Change-Id: I7d32dacaa1302bab61386f5bd69aaa7dde953ebe
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
index b11d7464..6f0001d 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
@@ -84,6 +84,7 @@
 
     private static class TestWindow extends BaseIWindow {
         final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
+        final InsetsState mRequestedVisibility = new InsetsState();
         final Rect mOutFrame = new Rect();
         final Rect mOutContentInsets = new Rect();
         final Rect mOutStableInsets = new Rect();
@@ -108,7 +109,8 @@
 
                 long startTime = SystemClock.elapsedRealtimeNanos();
                 session.addToDisplay(this, mLayoutParams, View.VISIBLE,
-                        Display.DEFAULT_DISPLAY, mOutFrame, mOutContentInsets, mOutStableInsets,
+                        Display.DEFAULT_DISPLAY, mRequestedVisibility, mOutFrame,
+                        mOutContentInsets, mOutStableInsets,
                         mOutDisplayCutout, inputChannel, mOutInsetsState, mOutControls);
                 final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime;
                 state.addExtraResult("add", elapsedTimeNsOfAdd);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 4d1337b..6a70a85 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -877,9 +877,10 @@
                         InputChannel inputChannel = new InputChannel();
 
                         if (mSession.addToDisplay(mWindow, mLayout, View.VISIBLE,
-                                mDisplay.getDisplayId(), mWinFrames.frame, mWinFrames.contentInsets,
-                                mWinFrames.stableInsets, mWinFrames.displayCutout, inputChannel,
-                                mInsetsState, mTempControls) < 0) {
+                                mDisplay.getDisplayId(), mInsetsState, mWinFrames.frame,
+                                mWinFrames.contentInsets, mWinFrames.stableInsets,
+                                mWinFrames.displayCutout, inputChannel, mInsetsState,
+                                mTempControls) < 0) {
                             Log.w(TAG, "Failed to add window while updating wallpaper surface.");
                             return;
                         }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 910fd90..7f36169 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -45,12 +45,13 @@
  */
 interface IWindowSession {
     int addToDisplay(IWindow window, in WindowManager.LayoutParams attrs,
-            in int viewVisibility, in int layerStackId, out Rect outFrame,
-            out Rect outContentInsets, out Rect outStableInsets,
+            in int viewVisibility, in int layerStackId, in InsetsState requestedVisibility,
+            out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
             out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
             out InsetsState insetsState, out InsetsSourceControl[] activeControls);
     int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs,
                 in int viewVisibility, in int layerStackId, in int userId,
+                in InsetsState requestedVisibility,
                 out Rect outFrame, out Rect outContentInsets, out Rect outStableInsets,
                 out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
                 out InsetsState insetsState, out InsetsSourceControl[] activeControls);
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 71899fa..878583b 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -212,21 +212,21 @@
     /**
      * @return Whether the finish callback of this animation should be invoked.
      */
-    public boolean applyChangeInsets(InsetsState state) {
+    public boolean applyChangeInsets(@Nullable InsetsState outState) {
         if (mCancelled) {
             if (DEBUG) Log.d(TAG, "applyChangeInsets canceled");
             return false;
         }
         final Insets offset = Insets.subtract(mShownInsets, mPendingInsets);
         ArrayList<SurfaceParams> params = new ArrayList<>();
-        updateLeashesForSide(ISIDE_LEFT, offset.left, mShownInsets.left, mPendingInsets.left,
-                params, state, mPendingAlpha);
-        updateLeashesForSide(ISIDE_TOP, offset.top, mShownInsets.top, mPendingInsets.top, params,
-                state, mPendingAlpha);
-        updateLeashesForSide(ISIDE_RIGHT, offset.right, mShownInsets.right, mPendingInsets.right,
-                params, state, mPendingAlpha);
-        updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mShownInsets.bottom,
-                mPendingInsets.bottom, params, state, mPendingAlpha);
+        updateLeashesForSide(ISIDE_LEFT, offset.left, mPendingInsets.left, params, outState,
+                mPendingAlpha);
+        updateLeashesForSide(ISIDE_TOP, offset.top, mPendingInsets.top, params, outState,
+                mPendingAlpha);
+        updateLeashesForSide(ISIDE_RIGHT, offset.right, mPendingInsets.right, params, outState,
+                mPendingAlpha);
+        updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mPendingInsets.bottom, params, outState,
+                mPendingAlpha);
 
         mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()]));
         mCurrentInsets = mPendingInsets;
@@ -357,8 +357,8 @@
         return alpha >= 1 ? 1 : (alpha <= 0 ? 0 : alpha);
     }
 
-    private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int maxInset,
-            int inset, ArrayList<SurfaceParams> surfaceParams, InsetsState state, Float alpha) {
+    private void updateLeashesForSide(@InternalInsetsSide int side, int offset, int inset,
+            ArrayList<SurfaceParams> surfaceParams, @Nullable InsetsState outState, float alpha) {
         ArraySet<InsetsSourceControl> items = mSideSourceMap.get(side);
         if (items == null) {
             return;
@@ -377,8 +377,10 @@
                     ? (mAnimationType == ANIMATION_TYPE_SHOW ? true : !mFinished)
                     : inset != 0;
 
-            state.getSource(source.getType()).setVisible(visible);
-            state.getSource(source.getType()).setFrame(mTmpFrame);
+            if (outState != null) {
+                outState.getSource(source.getType()).setVisible(visible);
+                outState.getSource(source.getType()).setFrame(mTmpFrame);
+            }
 
             // If the system is controlling the insets source, the leash can be null.
             if (leash != null) {
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index cc3cd27..1307052 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -44,7 +44,6 @@
     private final InsetsAnimationControlImpl mControl;
     private final InsetsAnimationControlCallbacks mOuterCallbacks;
     private final Handler mMainThreadHandler;
-    private final InsetsState mState = new InsetsState();
     private final InsetsAnimationControlCallbacks mCallbacks =
             new InsetsAnimationControlCallbacks() {
 
@@ -60,7 +59,7 @@
 
         @Override
         public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
-            mControl.applyChangeInsets(mState);
+            mControl.applyChangeInsets(null /* outState */);
         }
 
         @Override
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 652781a..5037d9e 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -484,7 +484,9 @@
     /** The state dispatched from server */
     private final InsetsState mLastDispatchedState = new InsetsState();
 
-    /** The state sent to server */
+    // TODO: Use other class to represent the requested visibility of each type, because the
+    //       display frame and the frame in each source are not used.
+    /** The requested visibilities sent to server */
     private final InsetsState mRequestedState = new InsetsState();
 
     private final Rect mFrame = new Rect();
@@ -499,6 +501,7 @@
     private final List<WindowInsetsAnimation> mUnmodifiableTmpRunningAnims =
             Collections.unmodifiableList(mTmpRunningAnims);
     private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
+    private final ArraySet<InsetsSourceConsumer> mRequestedVisibilityChanged = new ArraySet<>();
     private WindowInsets mLastInsets;
 
     private boolean mAnimCallbackScheduled;
@@ -640,11 +643,6 @@
             if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
             mHost.notifyInsetsChanged();
         }
-        if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */,
-                true /* excludeInvisibleIme */)) {
-            if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState);
-            updateRequestedState();
-        }
         return true;
     }
 
@@ -808,9 +806,9 @@
         if (hideTypes[0] != 0) {
             applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
         }
-        if (requestedStateStale) {
-            updateRequestedState();
-        }
+
+        // InsetsSourceConsumer#setControl might change the requested visibility.
+        updateRequestedVisibility();
     }
 
     @Override
@@ -945,6 +943,7 @@
         if (types == 0) {
             // nothing to animate.
             listener.onCancelled(null);
+            updateRequestedVisibility();
             if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked");
             return;
         }
@@ -980,12 +979,14 @@
                     }
                 });
             }
+            updateRequestedVisibility();
             return;
         }
 
         if (typesReady == 0) {
             if (DEBUG) Log.d(TAG, "No types ready. onCancelled()");
             listener.onCancelled(null);
+            updateRequestedVisibility();
             return;
         }
 
@@ -1010,6 +1011,7 @@
         } else {
             hideDirectly(types, false /* animationFinished */, animationType);
         }
+        updateRequestedVisibility();
     }
 
     /**
@@ -1177,7 +1179,6 @@
         }
         if (stateChanged) {
             mHost.notifyInsetsChanged();
-            updateRequestedState();
         }
     }
 
@@ -1202,7 +1203,6 @@
     @VisibleForTesting
     public void notifyVisibilityChanged() {
         mHost.notifyInsetsChanged();
-        updateRequestedState();
     }
 
     /**
@@ -1251,38 +1251,39 @@
         return ANIMATION_TYPE_NONE;
     }
 
+    @VisibleForTesting
+    public void onRequestedVisibilityChanged(InsetsSourceConsumer consumer) {
+        mRequestedVisibilityChanged.add(consumer);
+    }
+
     /**
-     * Sends the local visibility state back to window manager if it is changed.
+     * Sends the requested visibilities to window manager if any of them is changed.
      */
-    private void updateRequestedState() {
+    private void updateRequestedVisibility() {
         boolean changed = false;
-        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
-            final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+        for (int i = mRequestedVisibilityChanged.size() - 1; i >= 0; i--) {
+            final InsetsSourceConsumer consumer = mRequestedVisibilityChanged.valueAt(i);
             final @InternalInsetsType int type = consumer.getType();
             if (type == ITYPE_CAPTION_BAR) {
                 continue;
             }
-            if (consumer.getControl() != null) {
-                final InsetsSource localSource = mState.getSource(type);
-                if (!localSource.equals(mRequestedState.peekSource(type))) {
-                    // Our requested state is stale. Update it here and send it to window manager.
-                    mRequestedState.addSource(new InsetsSource(localSource));
-                    changed = true;
-                }
-                if (!localSource.equals(mLastDispatchedState.peekSource(type))) {
-                    // The server state is not what we expected. This can happen while we don't have
-                    // the control. Since we have the control now, we need to send our request again
-                    // to modify the server state.
-                    changed = true;
-                }
+            final boolean requestedVisible = consumer.isRequestedVisible();
+            if (requestedVisible != mRequestedState.getSourceOrDefaultVisibility(type)) {
+                mRequestedState.getSource(type).setVisible(requestedVisible);
+                changed = true;
             }
         }
+        mRequestedVisibilityChanged.clear();
         if (!changed) {
             return;
         }
         mHost.onInsetsModified(mRequestedState);
     }
 
+    InsetsState getRequestedVisibility() {
+        return mRequestedState;
+    }
+
     @VisibleForTesting
     public void applyAnimation(@InsetsType final int types, boolean show, boolean fromIme) {
         if (types == 0) {
@@ -1316,6 +1317,7 @@
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             getSourceConsumer(internalTypes.valueAt(i)).hide(animationFinished, animationType);
         }
+        updateRequestedVisibility();
     }
 
     private void showDirectly(@InsetsType int types) {
@@ -1326,6 +1328,7 @@
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             getSourceConsumer(internalTypes.valueAt(i)).show(false /* fromIme */);
         }
+        updateRequestedVisibility();
     }
 
     /**
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index d7ceaf7..e4a24eb 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -350,6 +350,7 @@
         if (mRequestedVisible != requestedVisible) {
             mRequestedVisible = requestedVisible;
             mIsAnimationPending = false;
+            mController.onRequestedVisibilityChanged(this);
             if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible);
         }
         if (applyLocalVisibilityOverride()) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 38441d1..b9f1f6a 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -63,8 +63,6 @@
  */
 public class InsetsState implements Parcelable {
 
-    public static final InsetsState EMPTY = new InsetsState();
-
     /**
      * Internal representation of inset source types. This is different from the public API in
      * {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5235740..d2607c9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1021,8 +1021,10 @@
                     mAttachInfo.mRecomputeGlobalAttributes = true;
                     collectViewAttributes();
                     adjustLayoutParamsForCompatibility(mWindowAttributes);
+                    controlInsetsForCompatibility(mWindowAttributes);
                     res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
-                            getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrames.frame,
+                            getHostVisibility(), mDisplay.getDisplayId(), userId,
+                            mInsetsController.getRequestedVisibility(), mTmpFrames.frame,
                             mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                             mAttachInfo.mDisplayCutout, inputChannel,
                             mTempInsets, mTempControls);
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 90a80ce..8f58df4 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -144,7 +144,9 @@
     @Override
     public void onInsetsModified(InsetsState insetsState) {
         try {
-            mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+            if (mViewRoot.mAdded) {
+                mViewRoot.mWindowSession.insetsModified(mViewRoot.mWindow, insetsState);
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to call insetsModified", e);
         }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 0c221ed..8147873 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -130,8 +130,8 @@
      */
     @Override
     public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
-            Rect outStableInsets,
+            int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
@@ -166,11 +166,11 @@
      */
     @Override
     public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, int userId, Rect outFrame,
-            Rect outContentInsets, Rect outStableInsets,
+            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
+            Rect outFrame, Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
-        return addToDisplay(window, attrs, viewVisibility, displayId,
+        return addToDisplay(window, attrs, viewVisibility, displayId, requestedVisibility,
                 outFrame, outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
                 outInsetsState, outActiveControls);
     }
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 8412e53..b98ce30 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -89,6 +90,7 @@
         mInsetsState = new InsetsState();
         mInsetsState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 500, 100));
         mInsetsState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500));
+        doNothing().when(mMockController).onRequestedVisibilityChanged(any());
         InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mInsetsState,
                 () -> mMockTransaction, mMockController);
         topConsumer.setControl(
@@ -130,7 +132,7 @@
     public void testChangeInsets() {
         mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 1f /* alpha */,
                 0f /* fraction */);
-        mController.applyChangeInsets(new InsetsState());
+        mController.applyChangeInsets(null /* outState */);
         assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
         assertEquals(1f, mController.getCurrentAlpha(), 1f - mController.getCurrentAlpha());
 
@@ -150,7 +152,7 @@
     public void testChangeAlphaNoInsets() {
         Insets initialInsets = mController.getCurrentInsets();
         mController.setInsetsAndAlpha(null, 0.5f, 0f /* fraction*/);
-        mController.applyChangeInsets(new InsetsState());
+        mController.applyChangeInsets(null /* outState */);
         assertEquals(0.5f, mController.getCurrentAlpha(), 0.5f - mController.getCurrentAlpha());
         assertEquals(initialInsets, mController.getCurrentInsets());
     }
@@ -158,7 +160,7 @@
     @Test
     public void testChangeInsetsAndAlpha() {
         mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 0.5f, 1f);
-        mController.applyChangeInsets(new InsetsState());
+        mController.applyChangeInsets(null /* outState */);
         assertEquals(0.5f, mController.getCurrentAlpha(), 0.5f - mController.getCurrentAlpha());
         assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
     }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index cc97eb5..7b84f68c 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -683,71 +683,15 @@
     @Test
     public void testRequestedState() {
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            final InsetsState state = mTestHost.getRequestedState();
 
-            // The modified state can be controlled when we have control.
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
-            mController.hide(statusBars());
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
+            mController.hide(statusBars() | navigationBars());
+            assertFalse(state.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR));
+            assertFalse(state.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
 
-            // The modified state won't be changed while losing control.
-            mController.onControlsChanged(null /* activeControls */);
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state won't be changed while state changed while we don't have control.
-            InsetsState newState = new InsetsState(mController.getState(), true /* copySource */);
-            mController.onStateChanged(newState);
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state won't be changed while controlling an insets without having the
-            // control.
-            mController.show(statusBars());
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state can be updated while gaining control.
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
-            assertTrue(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state can still be updated if the local state and the requested state
-            // are the same.
-            mController.onControlsChanged(null /* activeControls */);
-            mController.hide(statusBars());
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-            mController.onStateChanged(newState);
-            mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
-            assertFalse(mTestHost.getModifiedState().peekSource(ITYPE_STATUS_BAR).isVisible());
-
-            // The modified state will always be updated while receiving IME control if IME is
-            // requested visible.
-            mController.getSourceConsumer(ITYPE_IME).show(false /* fromIme */);
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_IME).setVisible(true);
-            newState.getSource(ITYPE_IME).setFrame(1, 2, 3, 4);
-            mController.onStateChanged(newState);
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME));
-            assertEquals(newState.getSource(ITYPE_IME),
-                    mTestHost.getModifiedState().peekSource(ITYPE_IME));
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_IME).setVisible(true);
-            newState.getSource(ITYPE_IME).setFrame(5, 6, 7, 8);
-            mController.onStateChanged(newState);
-            mController.onControlsChanged(createSingletonControl(ITYPE_IME));
-            assertEquals(newState.getSource(ITYPE_IME),
-                    mTestHost.getModifiedState().peekSource(ITYPE_IME));
-
-            // The modified frames cannot be updated if there is an animation.
-            mController.onControlsChanged(createSingletonControl(ITYPE_NAVIGATION_BAR));
-            mController.hide(navigationBars());
-            newState = new InsetsState(mController.getState(), true /* copySource */);
-            newState.getSource(ITYPE_NAVIGATION_BAR).getFrame().top--;
-            mController.onStateChanged(newState);
-            assertNotEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
-                    mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
-
-            // The modified frames can be updated while the animation is done.
-            mController.cancelExistingAnimations();
-            assertEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
-                    mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
+            mController.show(statusBars() | navigationBars());
+            assertTrue(state.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR));
+            assertTrue(state.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
         });
     }
 
@@ -878,7 +822,7 @@
 
     public static class TestHost extends ViewRootInsetsControllerHost {
 
-        private InsetsState mModifiedState = new InsetsState();
+        private final InsetsState mRequestedState = new InsetsState();
 
         TestHost(ViewRootImpl viewRoot) {
             super(viewRoot);
@@ -886,12 +830,12 @@
 
         @Override
         public void onInsetsModified(InsetsState insetsState) {
-            mModifiedState = new InsetsState(insetsState, true /* copySource */);
+            mRequestedState.set(insetsState, true);
             super.onInsetsModified(insetsState);
         }
 
-        public InsetsState getModifiedState() {
-            return mModifiedState;
+        public InsetsState getRequestedState() {
+            return mRequestedState;
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index be03e91..0291611 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -192,6 +192,8 @@
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputWindowHandle;
+import android.view.InsetsSource;
+import android.view.InsetsState;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.MagnificationSpec;
 import android.view.RemoteAnimationDefinition;
@@ -4826,7 +4828,7 @@
             boolean ignoreRequest) {
         final int type = win.mAttrs.type;
         final boolean stickyHideNav =
-                !win.getRequestedInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+                !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                         && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
         return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD
                 && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME;
@@ -5553,6 +5555,7 @@
 
     class RemoteInsetsControlTarget implements InsetsControlTarget {
         private final IDisplayWindowInsetsController mRemoteInsetsController;
+        private final InsetsState mRequestedInsetsState = new InsetsState();
 
         RemoteInsetsControlTarget(IDisplayWindowInsetsController controller) {
             mRemoteInsetsController = controller;
@@ -5608,6 +5611,19 @@
                 Slog.w(TAG, "Failed to deliver showInsets", e);
             }
         }
+
+        @Override
+        public boolean getRequestedVisibility(@InternalInsetsType int type) {
+            return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
+        }
+
+        void updateRequestedVisibility(InsetsState state) {
+            for (int i = 0; i < InsetsState.SIZE; i++) {
+                final InsetsSource source = state.peekSource(i);
+                if (source == null) continue;
+                mRequestedInsetsState.addSource(source);
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4e7e0ba..b2cf856 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1659,10 +1659,8 @@
                 provider != null ? provider.getControlTarget() : null;
         final WindowState navControllingWin =
                 navControlTarget instanceof WindowState ? (WindowState) navControlTarget : null;
-        final InsetsState requestedState = navControllingWin != null
-                ? navControllingWin.getRequestedInsetsState() : null;
-        final boolean navVisible = requestedState != null
-                ? requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+        final boolean navVisible = navControllingWin != null
+                ? navControllingWin.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                 : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR);
         final boolean showBarsByTouch = navControllingWin != null
                 && navControllingWin.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_BARS_BY_TOUCH;
@@ -2073,11 +2071,10 @@
         // the cutout safe zone.
         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
             final boolean attachedInParent = attached != null && !layoutInScreen;
-            final InsetsState requestedInsetsState = win.getRequestedInsetsState();
             final boolean requestedFullscreen = (fl & FLAG_FULLSCREEN) != 0
-                    || !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR);
+                    || !win.getRequestedVisibility(ITYPE_STATUS_BAR);
             final boolean requestedHideNavigation =
-                    !requestedInsetsState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+                    !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
 
             // TYPE_BASE_APPLICATION windows are never considered floating here because they don't
             // get cropped / shifted to the displayFrame in WindowState.
@@ -2423,14 +2420,8 @@
         }
         final LayoutParams attrs = mTopFullscreenOpaqueWindowState.getAttrs();
         final int fl = attrs.flags;
-        final InsetsSource request = mTopFullscreenOpaqueWindowState.getRequestedInsetsState()
-                .peekSource(ITYPE_STATUS_BAR);
-        if (WindowManagerDebugConfig.DEBUG) {
-            Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrame());
-            Slog.d(TAG, "attr: " + attrs + " request: " + request);
-        }
         return (fl & LayoutParams.FLAG_FULLSCREEN) != 0
-                || (request != null && !request.isVisible());
+                || !mTopFullscreenOpaqueWindowState.getRequestedVisibility(ITYPE_STATUS_BAR);
     }
 
     /**
@@ -2864,18 +2855,15 @@
             return;
         }
 
-        final InsetsState requestedState = controlTarget.getRequestedInsetsState();
         final @InsetsType int restorePositionTypes =
-                (requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+                (controlTarget.getRequestedVisibility(ITYPE_NAVIGATION_BAR)
                         ? Type.navigationBars() : 0)
-                | (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
+                | (controlTarget.getRequestedVisibility(ITYPE_STATUS_BAR)
                         ? Type.statusBars() : 0)
-                | (mExtraNavBarAlt != null
-                        && requestedState.getSourceOrDefaultVisibility(
+                | (mExtraNavBarAlt != null && controlTarget.getRequestedVisibility(
                                 ITYPE_EXTRA_NAVIGATION_BAR)
                         ? Type.navigationBars() : 0)
-                | (mClimateBarAlt != null
-                        && requestedState.getSourceOrDefaultVisibility(
+                | (mClimateBarAlt != null && controlTarget.getRequestedVisibility(
                                 ITYPE_CLIMATE_BAR)
                         ? Type.statusBars() : 0);
 
@@ -2981,12 +2969,11 @@
                 win.mAttrs.insetsFlags.appearance, mTopFullscreenOpaqueWindowState,
                 mTopFullscreenOpaqueOrDimmingWindowState,
                 mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance;
-        final InsetsState requestedInsets = win.getRequestedInsetsState();
         final int behavior = win.mAttrs.insetsFlags.behavior;
         final boolean isImmersive = behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
                 || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
-        final boolean isFullscreen = !requestedInsets.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
-                || !requestedInsets.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR);
+        final boolean isFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR)
+                || !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
         if (mLastDisableFlags == disableFlags
                 && mLastAppearance == appearance
                 && mLastFullscreenAppearance == fullscreenAppearance
@@ -3152,10 +3139,7 @@
                 freeformStackVisible, resizing, fullscreenDrawsNavBarBackground,
                 dockedDrawsNavigationBarBackground);
 
-        final InsetsState requestedInsetsState = win.getRequestedInsetsState();
-        final boolean requestHideNavBar = !requestedInsetsState.getSourceOrDefaultVisibility(
-                        ITYPE_NAVIGATION_BAR);
-
+        final boolean requestHideNavBar = !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
         final long now = SystemClock.uptimeMillis();
         final boolean pendingPanic = mPendingPanicGestureUptime != 0
                 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java
index 5e7ed3f..287dd74 100644
--- a/services/core/java/com/android/server/wm/InsetsControlTarget.java
+++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java
@@ -18,6 +18,7 @@
 
 import android.inputmethodservice.InputMethodService;
 import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
 import android.view.WindowInsets.Type.InsetsType;
 
 /**
@@ -39,10 +40,10 @@
     }
 
     /**
-     * @return The requested {@link InsetsState} of this target.
+     * @return The requested visibility of this target.
      */
-    default InsetsState getRequestedInsetsState() {
-        return InsetsState.EMPTY;
+    default boolean getRequestedVisibility(@InternalInsetsType int type) {
+        return InsetsState.getDefaultVisibility(type);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3617884..bd05da9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -173,13 +173,7 @@
             // animation frame which will be triggered if a new leash is created.
             mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> {
                 synchronized (mDisplayContent.mWmService.mGlobalLock) {
-                    final InsetsState state = new InsetsState(mStateController.getRawInsetsState());
-                    startAnimation(true /* show */, () -> {
-                        synchronized (mDisplayContent.mWmService.mGlobalLock) {
-                            mStateController.notifyInsetsChanged();
-                        }
-                    }, state);
-                    mStateController.onInsetsModified(mDummyControlTarget, state);
+                    startAnimation(true /* show */, null /* callback */);
                 }
             });
         }
@@ -189,15 +183,18 @@
         if (mShowingTransientTypes.size() == 0) {
             return;
         }
-        InsetsState state = new InsetsState(mStateController.getRawInsetsState());
         startAnimation(false /* show */, () -> {
             synchronized (mDisplayContent.mWmService.mGlobalLock) {
+                for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
+                    // We are about to clear mShowingTransientTypes, we don't want the transient bar
+                    // can cause insets on the client. Restore the client visibility.
+                    final @InternalInsetsType int type = mShowingTransientTypes.get(i);
+                    mStateController.getSourceProvider(type).setClientVisible(false);
+                }
                 mShowingTransientTypes.clear();
-                mStateController.notifyInsetsChanged();
                 updateBarControlTarget(mFocusedWin);
             }
-        }, state);
-        mStateController.onInsetsModified(mDummyControlTarget, state);
+        });
     }
 
     boolean isTransient(@InternalInsetsType int type) {
@@ -211,7 +208,7 @@
         final InsetsState originalState = mStateController.getInsetsForDispatch(target);
         InsetsState state = originalState;
         for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-            final int type = mShowingTransientTypes.get(i);
+            final @InternalInsetsType int type = mShowingTransientTypes.get(i);
             final InsetsSource originalSource = state.peekSource(type);
             if (originalSource != null && originalSource.isVisible()) {
                 if (state == originalState) {
@@ -227,26 +224,25 @@
         return state;
     }
 
-    void onInsetsModified(WindowState windowState, InsetsState state) {
-        mStateController.onInsetsModified(windowState, state);
-        checkAbortTransient(windowState, state);
+    void onInsetsModified(InsetsControlTarget caller) {
+        mStateController.onInsetsModified(caller);
+        checkAbortTransient(caller);
         updateBarControlTarget(mFocusedWin);
     }
 
     /**
-     * Called when a window modified the insets state. If the window set a insets source to visible
-     * while it is shown transiently, we need to abort the transient state.
+     * Called when a control target modified the insets state. If the target set a insets source to
+     * visible while it is shown transiently, we need to abort the transient state.
      *
-     * @param windowState who changed the insets state.
-     * @param state the modified insets state.
+     * @param caller who changed the insets state.
      */
-    private void checkAbortTransient(WindowState windowState, InsetsState state) {
+    private void checkAbortTransient(InsetsControlTarget caller) {
         if (mShowingTransientTypes.size() != 0) {
             IntArray abortTypes = new IntArray();
             for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
-                final int type = mShowingTransientTypes.get(i);
-                if (mStateController.isFakeTarget(type, windowState)
-                        && state.getSource(type).isVisible()) {
+                final @InternalInsetsType int type = mShowingTransientTypes.get(i);
+                if (mStateController.isFakeTarget(type, caller)
+                        && caller.getRequestedVisibility(type)) {
                     mShowingTransientTypes.remove(i);
                     abortTypes.add(type);
                 }
@@ -393,12 +389,12 @@
     }
 
     @VisibleForTesting
-    void startAnimation(boolean show, Runnable callback, InsetsState state) {
+    void startAnimation(boolean show, Runnable callback) {
         int typesReady = 0;
         final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
         final IntArray showingTransientTypes = mShowingTransientTypes;
         for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
-            int type = showingTransientTypes.get(i);
+            final @InternalInsetsType int type = showingTransientTypes.get(i);
             InsetsSourceProvider provider = mStateController.getSourceProvider(type);
             InsetsSourceControl control = provider.getControl(mDummyControlTarget);
             if (control == null || control.getLeash() == null) {
@@ -406,7 +402,6 @@
             }
             typesReady |= InsetsState.toPublicType(type);
             controls.put(control.getType(), new InsetsSourceControl(control));
-            state.setSourceVisible(type, show);
         }
         controlAnimationUnchecked(typesReady, controls, show, callback);
     }
@@ -428,12 +423,9 @@
             mId = id;
         }
 
-        private void updateVisibility(InsetsControlTarget controlTarget,
+        private void updateVisibility(@Nullable InsetsControlTarget controlTarget,
                 @InternalInsetsType int type) {
-            final WindowState controllingWin =
-                    controlTarget instanceof WindowState ? (WindowState) controlTarget : null;
-            setVisible(controllingWin == null
-                    || controllingWin.getRequestedInsetsState().getSourceOrDefaultVisibility(type));
+            setVisible(controlTarget == null || controlTarget.getRequestedVisibility(type));
         }
 
         private void setVisible(boolean visible) {
@@ -463,7 +455,9 @@
         @Override
         protected void onAnimationFinish() {
             super.onAnimationFinish();
-            DisplayThread.getHandler().post(mFinishCallback);
+            if (mFinishCallback != null) {
+                DisplayThread.getHandler().post(mFinishCallback);
+            }
         }
 
         private class InsetsPolicyAnimationControlCallbacks implements
@@ -484,7 +478,7 @@
                 mAnimatingShown = show;
 
                 mAnimationControl = new InsetsAnimationControlImpl(controls,
-                        mFocusedWin.getDisplayContent().getBounds(), getState(),
+                        mFocusedWin.getDisplayContent().getBounds(), mFocusedWin.getInsetsState(),
                         mListener, typesReady, this, mListener.getDurationMs(),
                         InsetsController.SYSTEM_BARS_INTERPOLATOR,
                         show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE);
@@ -495,8 +489,7 @@
             /** Called on SurfaceAnimationThread without global WM lock held. */
             @Override
             public void scheduleApplyChangeInsets(InsetsAnimationControlRunner runner) {
-                InsetsState state = getState();
-                if (mAnimationControl.applyChangeInsets(state)) {
+                if (mAnimationControl.applyChangeInsets(null /* outState */)) {
                     mAnimationControl.finish(mAnimatingShown);
                 }
             }
@@ -507,20 +500,6 @@
                 // onAnimationFinished callback.
             }
 
-            /**
-             * This method will return a state with fullscreen frame override. No need to make copy
-             * after getting state from this method.
-             * @return The client insets state with full display frame override.
-             */
-            private InsetsState getState() {
-                // To animate the transient animation correctly, we need to let the state hold
-                // the full display frame.
-                InsetsState overrideState = new InsetsState(mFocusedWin.getRequestedInsetsState(),
-                        true);
-                overrideState.setDisplayFrame(mFocusedWin.getDisplayContent().getBounds());
-                return overrideState;
-            }
-
             /** Called on SurfaceAnimationThread without global WM lock held. */
             @Override
             public void applySurfaceParams(
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 7defc5d..e83151d 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -338,11 +338,12 @@
         }
     }
 
-    boolean onInsetsModified(InsetsControlTarget caller, InsetsSource modifiedSource) {
-        if (mControlTarget != caller || modifiedSource.isVisible() == mClientVisible) {
+    boolean updateClientVisibility(InsetsControlTarget caller) {
+        final boolean requestedVisible = caller.getRequestedVisibility(mSource.getType());
+        if (caller != mControlTarget || requestedVisible == mClientVisible) {
             return false;
         }
-        setClientVisible(modifiedSource.isVisible());
+        setClientVisible(requestedVisible);
         return true;
     }
 
@@ -350,7 +351,7 @@
         mIsLeashReadyForDispatching = true;
     }
 
-    private void setClientVisible(boolean clientVisible) {
+    void setClientVisible(boolean clientVisible) {
         if (mClientVisible == clientVisible) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index b59452f..b9c2093 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -289,16 +289,10 @@
         winInsetsChanged.clear();
     }
 
-    void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
+    void onInsetsModified(InsetsControlTarget caller) {
         boolean changed = false;
-        for (int i = 0; i < InsetsState.SIZE; i++) {
-            final InsetsSource source = state.peekSource(i);
-            if (source == null) continue;
-            final InsetsSourceProvider provider = mProviders.get(source.getType());
-            if (provider == null) {
-                continue;
-            }
-            changed |= provider.onInsetsModified(windowState, source);
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            changed |= mProviders.valueAt(i).updateClientVisibility(caller);
         }
         if (changed) {
             notifyInsetsChanged();
@@ -464,11 +458,24 @@
                 final InsetsSourceProvider provider = mProviders.valueAt(i);
                 provider.onSurfaceTransactionApplied();
             }
+            final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>();
             for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
                 final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
                 controlTarget.notifyInsetsControlChanged();
+                if (mControlTargetTypeMap.containsKey(controlTarget)) {
+                    // We only collect targets who get controls, not lose controls.
+                    newControlTargets.add(controlTarget);
+                }
             }
             mPendingControlChanged.clear();
+
+            // This updates the insets visibilities AFTER sending current insets state and controls
+            // to the clients, so that the clients can change the current visibilities to the
+            // requested visibilities with animations.
+            for (int i = newControlTargets.size() - 1; i >= 0; i--) {
+                onInsetsModified(newControlTargets.valueAt(i));
+            }
+            newControlTargets.clear();
         });
     }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 02230d6..f84e70e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -92,6 +92,7 @@
     private float mLastReportedAnimatorScale;
     private String mPackageName;
     private String mRelayoutTag;
+    private final InsetsState mDummyRequestedVisibility = new InsetsState();
     private final InsetsSourceControl[] mDummyControls =  new InsetsSourceControl[0];
 
     public Session(WindowManagerService service, IWindowSessionCallback callback) {
@@ -158,25 +159,26 @@
 
     @Override
     public int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
-            Rect outStableInsets,
+            int viewVisibility, int displayId, InsetsState requestedVisibility, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
-        return mService.addWindow(this, window, attrs, viewVisibility, displayId, outFrame,
+        return mService.addWindow(this, window, attrs, viewVisibility, displayId,
+                UserHandle.getUserId(mUid), requestedVisibility, outFrame,
                 outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
-                outInsetsState, outActiveControls, UserHandle.getUserId(mUid));
+                outInsetsState, outActiveControls);
     }
 
 
     @Override
     public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
-            int viewVisibility, int displayId, int userId, Rect outFrame,
-            Rect outContentInsets, Rect outStableInsets,
+            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
+            Rect outFrame, Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
-        return mService.addWindow(this, window, attrs, viewVisibility, displayId, outFrame,
-                outContentInsets, outStableInsets, outDisplayCutout, outInputChannel,
-                outInsetsState, outActiveControls, userId);
+        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
+                requestedVisibility, outFrame, outContentInsets, outStableInsets, outDisplayCutout,
+                outInputChannel, outInsetsState, outActiveControls);
     }
 
     @Override
@@ -184,9 +186,10 @@
             int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
             InsetsState outInsetsState) {
         return mService.addWindow(this, window, attrs, viewVisibility, displayId,
+                UserHandle.getUserId(mUid), mDummyRequestedVisibility,
                 new Rect() /* outFrame */, outContentInsets, outStableInsets,
                 new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
-                outInsetsState, mDummyControls, UserHandle.getUserId(mUid));
+                outInsetsState, mDummyControls);
     }
 
     @Override
@@ -493,9 +496,8 @@
             final WindowState windowState = mService.windowForClientLocked(this, window,
                     false /* throwOnError */);
             if (windowState != null) {
-                windowState.updateRequestedInsetsState(state);
-                windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(
-                        windowState, state);
+                windowState.updateRequestedVisibility(state);
+                windowState.getDisplayContent().getInsetsPolicy().onInsetsModified(windowState);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 87b470a..01adb8b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -482,8 +482,7 @@
         final int color = ColorUtils.setAlphaComponent(
                 task.getTaskDescription().getBackgroundColor(), 255);
         final LayoutParams attrs = mainWindow.getAttrs();
-        final InsetsState insetsState = new InsetsState(mainWindow.getInsetsState());
-        mergeInsetsSources(insetsState, mainWindow.getRequestedInsetsState());
+        final InsetsState insetsState = getInsetsStateWithVisibilityOverride(mainWindow);
         final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
                 attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),
@@ -603,13 +602,18 @@
         return 0;
     }
 
-    static void mergeInsetsSources(InsetsState base, InsetsState other) {
+    static InsetsState getInsetsStateWithVisibilityOverride(WindowState win) {
+        final InsetsState state = new InsetsState(win.getInsetsState());
         for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
-            final InsetsSource source = other.peekSource(type);
-            if (source != null) {
-                base.addSource(source);
+            final boolean requestedVisible = win.getRequestedVisibility(type);
+            InsetsSource source = state.peekSource(type);
+            if (source != null && source.isVisible() != requestedVisible) {
+                source = new InsetsSource(source);
+                source.setVisible(requestedVisible);
+                state.addSource(source);
             }
         }
+        return state;
     }
 
     static Rect getSystemBarInsets(Rect frame, InsetsState state) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index efa0525..e8c4491 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -42,8 +42,8 @@
 import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
 import static com.android.internal.policy.DecorView.getNavigationBarRect;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.TaskSnapshotController.getInsetsStateWithVisibilityOverride;
 import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
-import static com.android.server.wm.TaskSnapshotController.mergeInsetsSources;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -236,14 +236,15 @@
             task.getBounds(taskBounds);
             currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
             activityType = activity.getActivityType();
-            insetsState = new InsetsState(topFullscreenOpaqueWindow.getInsetsState());
-            mergeInsetsSources(insetsState, topFullscreenOpaqueWindow.getRequestedInsetsState());
+            insetsState = getInsetsStateWithVisibilityOverride(topFullscreenOpaqueWindow);
+
         }
         try {
             final int res = session.addToDisplay(window, layoutParams,
-                    View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrames.frame,
-                    tmpFrames.contentInsets, tmpFrames.stableInsets, tmpFrames.displayCutout,
-                    null /* outInputChannel */, mTmpInsetsState, mTempControls);
+                    View.GONE, activity.getDisplayContent().getDisplayId(), mTmpInsetsState,
+                    tmpFrames.frame, tmpFrames.contentInsets, tmpFrames.stableInsets,
+                    tmpFrames.displayCutout, null /* outInputChannel */, mTmpInsetsState,
+                    mTempControls);
             if (res < 0) {
                 Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
                 return null;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4be118e..faa5de1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1377,10 +1377,10 @@
     }
 
     public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
-            int displayId, Rect outFrame, Rect outContentInsets, Rect outStableInsets,
+            int displayId, int requestUserId, InsetsState requestedVisibility, Rect outFrame,
+            Rect outContentInsets, Rect outStableInsets,
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
-            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
-            int requestUserId) {
+            InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         Arrays.fill(outActiveControls, null);
         int[] appOp = new int[1];
         final boolean isRoundedCornerOverlay = (attrs.privateFlags
@@ -1575,6 +1575,7 @@
 
             final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
             displayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid);
+            win.updateRequestedVisibility(requestedVisibility);
 
             res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
             if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -4014,8 +4015,8 @@
                 if (dc == null || dc.mRemoteInsetsControlTarget == null) {
                     return;
                 }
-                dc.getInsetsStateController().onInsetsModified(
-                        dc.mRemoteInsetsControlTarget, state);
+                dc.mRemoteInsetsControlTarget.updateRequestedVisibility(state);
+                dc.getInsetsStateController().onInsetsModified(dc.mRemoteInsetsControlTarget);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 25b4828..90c3d6c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -224,6 +224,7 @@
 import android.view.InputWindowHandle;
 import android.view.InsetsSource;
 import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetsType;
 import android.view.Surface.Rotation;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
@@ -719,20 +720,20 @@
     private final WindowProcessController mWpcForDisplayConfigChanges;
 
     /**
-     * @return The insets state as requested by the client, i.e. the dispatched insets state
-     *         for which the visibilities are overridden with what the client requested.
+     * Returns the visibility of the given {@link InternalInsetsType type} requested by the client.
+     *
+     * @param type the given {@link InternalInsetsType type}.
+     * @return {@code true} if the type is requested visible.
      */
     @Override
-    public InsetsState getRequestedInsetsState() {
-        return mRequestedInsetsState;
+    public boolean getRequestedVisibility(@InternalInsetsType int type) {
+        return mRequestedInsetsState.getSourceOrDefaultVisibility(type);
     }
 
     /**
-     * @see #getRequestedInsetsState()
+     * @see #getRequestedVisibility(int)
      */
-    void updateRequestedInsetsState(InsetsState state) {
-
-        // Only update the sources the client is actually controlling.
+    void updateRequestedVisibility(InsetsState state) {
         for (int i = 0; i < InsetsState.SIZE; i++) {
             final InsetsSource source = state.peekSource(i);
             if (source == null) continue;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index dd85484..ad9692f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1523,7 +1523,8 @@
             // Return error to skip unnecessary operation.
             doReturn(WindowManagerGlobal.ADD_STARTING_NOT_NEEDED).when(session).addToDisplay(
                     any() /* window */,  any() /* attrs */,
-                    anyInt() /* viewVisibility */, anyInt() /* displayId */, any() /* outFrame */,
+                    anyInt() /* viewVisibility */, anyInt() /* displayId */,
+                    any() /* requestedVisibility */, any() /* outFrame */,
                     any() /* outContentInsets */, any() /* outStableInsets */,
                     any() /* outDisplayCutout */, any() /* outInputChannel */,
                     any() /* outInsetsState */, any() /* outActiveControls */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 2920c1d..5a14a24 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -522,7 +522,9 @@
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
                 .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
-        mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
+        final InsetsState requestedState = new InsetsState();
+        requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        mWindow.updateRequestedVisibility(requestedState);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -544,7 +546,9 @@
         mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow)
                 .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
-        mWindow.getRequestedInsetsState().getSource(ITYPE_STATUS_BAR).setVisible(false);
+        final InsetsState requestedState = new InsetsState();
+        requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        mWindow.updateRequestedVisibility(requestedState);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         addWindow(mWindow);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index a55423a..21bdc9e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -313,8 +313,8 @@
         // App requests to hide navigation bar.
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
-        mAppWindow.updateRequestedInsetsState(requestedState);
-        insetsPolicy.onInsetsModified(mAppWindow, requestedState);
+        mAppWindow.updateRequestedVisibility(requestedState);
+        insetsPolicy.onInsetsModified(mAppWindow);
         assertNotNull(displayPolicy.mInputConsumer);
 
         // App still requests to hide navigation bar, but without BEHAVIOR_SHOW_BARS_BY_TOUCH.
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 8c02faf..d67120f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -38,7 +38,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -180,7 +179,7 @@
         final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp");
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        fullscreenApp.updateRequestedInsetsState(requestedState);
+        fullscreenApp.updateRequestedVisibility(requestedState);
 
         // Add a non-fullscreen dialog window.
         final WindowState dialog = addWindow(TYPE_APPLICATION, "dialog");
@@ -215,7 +214,7 @@
         final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp");
         final InsetsState newRequestedState = new InsetsState();
         newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true);
-        newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState);
+        newFocusedFullscreenApp.updateRequestedVisibility(newRequestedState);
         // Make sure status bar is hidden by previous insets state.
         mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp);
 
@@ -232,20 +231,28 @@
     @UseTestDisplay(addWindows = W_ACTIVITY)
     @Test
     public void testShowTransientBars_bothCanBeTransient_appGetsBothFakeControls() {
-        addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar")
-                .getControllableInsetProvider().getSource().setVisible(false);
-        addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
-                .getControllableInsetProvider().getSource().setVisible(false);
+        final WindowState statusBar = addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar");
+        statusBar.setHasSurface(true);
+        statusBar.getControllableInsetProvider().setServerVisible(true);
+        final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar");
+        navBar.setHasSurface(true);
+        navBar.getControllableInsetProvider().setServerVisible(true);
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
 
-        doAnswer(invocation -> {
-            ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_STATUS_BAR, true);
-            ((InsetsState) invocation.getArgument(2)).setSourceVisible(ITYPE_NAVIGATION_BAR, true);
-            return null;
-        }).when(policy).startAnimation(anyBoolean(), any(), any());
-
+        // Make both system bars invisible.
+        final InsetsState requestedState = new InsetsState();
+        requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false);
+        mAppWindow.updateRequestedVisibility(requestedState);
         policy.updateBarControlTarget(mAppWindow);
+        waitUntilWindowAnimatorIdle();
+        assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
+                .getSource(ITYPE_STATUS_BAR).isVisible());
+        assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState()
+                .getSource(ITYPE_NAVIGATION_BAR).isVisible());
+
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         waitUntilWindowAnimatorIdle();
         final InsetsSourceControl[] controls =
@@ -272,7 +279,7 @@
                 .getControllableInsetProvider().setServerVisible(true);
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
-        doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         waitUntilWindowAnimatorIdle();
@@ -301,7 +308,7 @@
                 .getControllableInsetProvider().getSource().setVisible(false);
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
-        doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(mAppWindow);
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         waitUntilWindowAnimatorIdle();
@@ -326,7 +333,8 @@
         assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible());
         assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
 
-        policy.onInsetsModified(mAppWindow, state);
+        mAppWindow.updateRequestedVisibility(state);
+        policy.onInsetsModified(mAppWindow);
         waitUntilWindowAnimatorIdle();
 
         controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow);
@@ -348,7 +356,7 @@
         final WindowState app2 = addWindow(TYPE_APPLICATION, "app");
 
         final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
-        doNothing().when(policy).startAnimation(anyBoolean(), any(), any());
+        doNothing().when(policy).startAnimation(anyBoolean(), any());
         policy.updateBarControlTarget(app);
         policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR});
         final InsetsSourceControl[] controls =
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index a0fa936..9830631 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -205,7 +205,8 @@
         mProvider.updateControlForTarget(target, false /* force */);
         InsetsState state = new InsetsState();
         state.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
+        target.updateRequestedVisibility(state);
+        mProvider.updateClientVisibility(target);
         assertFalse(mSource.isVisible());
     }
 
@@ -217,7 +218,8 @@
         mProvider.setWindow(statusBar, null, null);
         InsetsState state = new InsetsState();
         state.getSource(ITYPE_STATUS_BAR).setVisible(false);
-        mProvider.onInsetsModified(target, state.getSource(ITYPE_STATUS_BAR));
+        target.updateRequestedVisibility(state);
+        mProvider.updateClientVisibility(target);
         assertTrue(mSource.isVisible());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index e2cd8a9..c14df67 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -189,8 +189,8 @@
         getController().onImeControlTargetChanged(mDisplayContent.mInputMethodInputTarget);
         final InsetsState requestedState = new InsetsState();
         requestedState.getSource(ITYPE_IME).setVisible(true);
-        mDisplayContent.mInputMethodInputTarget.updateRequestedInsetsState(requestedState);
-        getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget, requestedState);
+        mDisplayContent.mInputMethodInputTarget.updateRequestedVisibility(requestedState);
+        getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget);
 
         // Send our spy window (app) into the system so that we can detect the invocation.
         final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index c18043f..19bed48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -71,7 +71,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.Size;
 import android.view.DisplayCutout;
-import android.view.InsetsSource;
+import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 
@@ -426,10 +426,11 @@
                 .setWindow(statusBar, null /* frameProvider */, null /* imeFrameProvider */);
         mDisplayContent.getInsetsStateController().onBarControlTargetChanged(
                 app, null /* fakeTopControlling */, app, null /* fakeNavControlling */);
-        final InsetsSource source = new InsetsSource(ITYPE_STATUS_BAR);
-        source.setVisible(false);
+        final InsetsState state = new InsetsState();
+        state.getSource(ITYPE_STATUS_BAR).setVisible(false);
+        app.updateRequestedVisibility(state);
         mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR)
-                .onInsetsModified(app, source);
+                .updateClientVisibility(app);
         waitUntilHandlersIdle();
         assertFalse(statusBar.isVisible());
     }