A brave new world for window insets (6/n)

Mirror state back to server

In case the client does some local visibility modification to the
leash, the server needs to be informed for a couple of reasons:

- Dispatching state to other apps
- Updating accessibility services
- Updating SystemUI/IME system

For that we send the state back whenever we modified it and send
it via IWindowSession.insetsModified. The server ensures that
visibility state is only updated if we have a match for the
controlling app, and then updates the visibility state and
dispatches it to other apps.

We also invert mHidden to mVisible in InsetsSourceConsumer as it
was really really confusing.

Bug: 118118435
Change-Id: I92f187bf892a5f26b8b007ed7e6fbf4d2c7b13e6
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 282838f..49a3186 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -21,6 +21,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.proto.ProtoOutputStream;
+import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.InsetsSource;
@@ -47,8 +48,18 @@
     private WindowState mWin;
     private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
 
+    /** The visibility override from the current controlling window. */
+    private boolean mClientVisible;
+
+    /**
+     * Whether the window is available and considered visible as in {@link WindowState#isVisible}.
+     */
+    private boolean mServerVisible;
+
+
     InsetsSourceProvider(InsetsSource source, InsetsStateController stateController,
             DisplayContent displayContent) {
+        mClientVisible = InsetsState.getDefaultVisibly(source.getType());
         mSource = source;
         mDisplayContent = displayContent;
         mStateController = stateController;
@@ -73,10 +84,9 @@
         mWin = win;
         mFrameProvider = frameProvider;
         if (win == null) {
-            mSource.setVisible(false);
+            setServerVisible(false);
             mSource.setFrame(new Rect());
         } else {
-            mSource.setVisible(true);
             mWin.setInsetProvider(this);
         }
     }
@@ -96,7 +106,7 @@
             mTmpRect.inset(mWin.mGivenContentInsets);
         }
         mSource.setFrame(mTmpRect);
-        mSource.setVisible(mWin.isVisible() && !mWin.mGivenInsetsPending);
+        setServerVisible(mWin.isVisible() && !mWin.mGivenInsetsPending);
 
     }
 
@@ -113,6 +123,29 @@
                 false /* TODO hidden */);
         mControllingWin = target;
         mControl = new InsetsSourceControl(mSource.getType(), mAdapter.mCapturedLeash);
+        setClientVisible(InsetsState.getDefaultVisibly(mSource.getType()));
+    }
+
+    boolean onInsetsModified(WindowState caller, InsetsSource modifiedSource) {
+        if (mControllingWin != caller || modifiedSource.isVisible() == mClientVisible) {
+            return false;
+        }
+        setClientVisible(modifiedSource.isVisible());
+        return true;
+    }
+
+    private void setClientVisible(boolean clientVisible) {
+        mClientVisible = clientVisible;
+        updateVisibility();
+    }
+
+    private void setServerVisible(boolean serverVisible) {
+        mServerVisible = serverVisible;
+        updateVisibility();
+    }
+
+    private void updateVisibility() {
+        mSource.setVisible(mServerVisible && mClientVisible);
     }
 
     InsetsSourceControl getControl() {
@@ -125,6 +158,7 @@
             // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
             mWin.cancelAnimation();
         }
+        setClientVisible(InsetsState.getDefaultVisibly(mSource.getType()));
     }
 
     private class ControlAdapter implements AnimationAdapter {
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 592b7fb..8e119bb 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -25,6 +25,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
+import android.view.InsetsSource;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.ViewRootImpl;
@@ -117,6 +118,21 @@
         }
     }
 
+    void onInsetsModified(WindowState windowState, InsetsState state) {
+        boolean changed = false;
+        for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
+            final InsetsSource source = state.sourceAt(i);
+            final InsetsSourceProvider provider = mControllers.get(source.getType());
+            if (provider == null) {
+                continue;
+            }
+            changed |= provider.onInsetsModified(windowState, source);
+        }
+        if (changed) {
+            notifyInsetsChanged();
+        }
+    }
+
     void onImeTargetChanged(@Nullable WindowState imeTarget) {
         onControlChanged(TYPE_IME, imeTarget);
         notifyPendingInsetsControlChanged();
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 37b5a7c..d85fdb0 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -430,6 +430,18 @@
         }
     }
 
+    @Override
+    public void insetsModified(IWindow window, InsetsState state) {
+        synchronized (mService.mWindowMap) {
+            final WindowState windowState = mService.windowForClientLocked(this, window,
+                    false /* throwOnError */);
+            if (windowState != null) {
+                windowState.getDisplayContent().getInsetsStateController().onInsetsModified(
+                        windowState, state);
+            }
+        }
+    }
+
     void windowAddedLocked(String packageName) {
         mPackageName = packageName;
         mRelayoutTag = "relayoutWindow: " + mPackageName;