Fix a couple of issues with insets

- Prevent any other animations running in WM that may override
the inset control.
- Ensure that we give the client control when the window gets
added.

Test: Show IME the first time
Bug: 111084606
Change-Id: I841d262103dc14e4aa71dbd37b696c76d822abd7
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index e49e4c0..e798203 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -16,7 +16,13 @@
 
 package com.android.server.wm;
 
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
+import static android.view.ViewRootImpl.sNewInsetsMode;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -59,6 +65,7 @@
      */
     private boolean mServerVisible;
 
+    private final boolean mControllable;
 
     InsetsSourceProvider(InsetsSource source, InsetsStateController stateController,
             DisplayContent displayContent) {
@@ -66,6 +73,15 @@
         mSource = source;
         mDisplayContent = displayContent;
         mStateController = stateController;
+
+        final int type = source.getType();
+        if (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR) {
+            mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL;
+        } else if (type == TYPE_IME) {
+            mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME;
+        } else {
+            mControllable = false;
+        }
     }
 
     InsetsSource getSource() {
@@ -73,6 +89,13 @@
     }
 
     /**
+     * @return Whether the current flag configuration allows to control this source.
+     */
+    boolean isControllable() {
+        return mControllable;
+    }
+
+    /**
      * Updates the window that currently backs this source.
      *
      * @param win The window that links to this source.
@@ -91,6 +114,9 @@
             mSource.setFrame(new Rect());
         } else {
             mWin.setInsetProvider(this);
+            if (mControllingWin != null) {
+                updateControlForTarget(mControllingWin, true /* force */);
+            }
         }
     }
 
@@ -113,8 +139,12 @@
                 && !mWin.mGivenInsetsPending);
     }
 
-    void updateControlForTarget(@Nullable WindowState target) {
-        if (target == mControllingWin) {
+    void updateControlForTarget(@Nullable WindowState target, boolean force) {
+        if (mWin == null) {
+            mControllingWin = target;
+            return;
+        }
+        if (target == mControllingWin && !force) {
             return;
         }
         if (target == null) {
@@ -161,7 +191,7 @@
     }
 
     boolean isClientVisible() {
-        return ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
+        return sNewInsetsMode == NEW_INSETS_MODE_NONE || mClientVisible;
     }
 
     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 c99839e..bb0cbb1 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -148,10 +148,6 @@
      *                          and visibility.
      */
     void onBarControllingWindowChanged(@Nullable WindowState controllingWindow) {
-        if (sNewInsetsMode != NEW_INSETS_MODE_FULL) {
-            return;
-        }
-
         // TODO: Apply policy that determines whether controllingWindow is able to control system
         // bars
 
@@ -167,18 +163,18 @@
     }
 
     private void onControlChanged(int type, @Nullable WindowState win) {
-        if (sNewInsetsMode == NEW_INSETS_MODE_NONE) {
-            return;
-        }
         final WindowState previous = mTypeWinControlMap.get(type);
         if (win == previous) {
             return;
         }
-        final InsetsSourceProvider controller = mControllers.get(type);
+        final InsetsSourceProvider controller = getSourceProvider(type);
         if (controller == null) {
             return;
         }
-        controller.updateControlForTarget(win);
+        if (!controller.isControllable()) {
+            return;
+        }
+        controller.updateControlForTarget(win, false /* force */);
         if (previous != null) {
             removeFromControlMaps(previous, type);
             mPendingControlChanged.add(previous);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8f86c00..7d900e5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4371,6 +4371,12 @@
     }
 
     void startAnimation(Animation anim) {
+
+        // If we are an inset provider, all our animations are driven by the inset client.
+        if (mInsetProvider != null && mInsetProvider.isControllable()) {
+            return;
+        }
+
         final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
         anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(),
                 displayInfo.appWidth, displayInfo.appHeight);
@@ -4384,6 +4390,12 @@
     }
 
     private void startMoveAnimation(int left, int top) {
+
+        // If we are an inset provider, all our animations are driven by the inset client.
+        if (mInsetProvider != null && mInsetProvider.isControllable()) {
+            return;
+        }
+
         if (DEBUG_ANIM) Slog.v(TAG, "Setting move animation on " + this);
         final Point oldPosition = new Point();
         final Point newPosition = new Point();
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 3740786..a498a1a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -94,9 +94,9 @@
         final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
         topBar.getFrameLw().set(0, 0, 500, 100);
         mProvider.setWindow(topBar, null);
-        mProvider.updateControlForTarget(target);
+        mProvider.updateControlForTarget(target, false /* force */);
         assertNotNull(mProvider.getControl());
-        mProvider.updateControlForTarget(null);
+        mProvider.updateControlForTarget(null, false /* force */);
         assertNull(mProvider.getControl());
     }
 
@@ -106,7 +106,7 @@
         final WindowState target = createWindow(null, TYPE_APPLICATION, "target");
         topBar.getFrameLw().set(0, 0, 500, 100);
         mProvider.setWindow(topBar, null);
-        mProvider.updateControlForTarget(target);
+        mProvider.updateControlForTarget(target, false /* force */);
         InsetsState state = new InsetsState();
         state.getSource(TYPE_TOP_BAR).setVisible(false);
         mProvider.onInsetsModified(target, state.getSource(TYPE_TOP_BAR));