Replace OnContentApplyWindowInsetsListener with simple boolean

The concept will move into the support library (androidx), so in
the framework we only need a simple boolean to toggle the default
behavior.

Also remove redundant methods on WIC to control IME.

Bug: 143556682
Bug: 118118435
Test: WindowTest CTS
Change-Id: I30fbffdfbe79a57b0f4166f0657c78370c7bcf02
diff --git a/api/current.txt b/api/current.txt
index 1306bfa..d5a0ba4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -54811,7 +54811,6 @@
     method public final void removeOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener);
     method public boolean requestFeature(int);
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
-    method public void resetOnContentApplyWindowInsetsListener();
     method public abstract void restoreHierarchyState(android.os.Bundle);
     method public abstract android.os.Bundle saveHierarchyState();
     method public void setAllowEnterTransitionOverlap(boolean);
@@ -54829,6 +54828,7 @@
     method public abstract void setContentView(android.view.View);
     method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public abstract void setDecorCaptionShade(int);
+    method public void setDecorFitsSystemWindows(boolean);
     method protected void setDefaultWindowFormat(int);
     method public void setDimAmount(float);
     method public void setElevation(float);
@@ -54850,7 +54850,6 @@
     method public abstract void setNavigationBarColor(@ColorInt int);
     method public void setNavigationBarContrastEnforced(boolean);
     method public void setNavigationBarDividerColor(@ColorInt int);
-    method public void setOnContentApplyWindowInsetsListener(@Nullable android.view.Window.OnContentApplyWindowInsetsListener);
     method public void setPreferMinimalPostProcessing(boolean);
     method public void setReenterTransition(android.transition.Transition);
     method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
@@ -54945,10 +54944,6 @@
     method @Nullable public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
   }
 
-  public static interface Window.OnContentApplyWindowInsetsListener {
-    method @NonNull public android.util.Pair<android.graphics.Insets,android.view.WindowInsets> onContentApplyWindowInsets(@NonNull android.view.WindowInsets);
-  }
-
   public static interface Window.OnFrameMetricsAvailableListener {
     method public void onFrameMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
   }
@@ -55099,16 +55094,13 @@
   }
 
   public interface WindowInsetsController {
-    method public default void controlInputMethodAnimation(long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener);
     method public void controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener);
     method public int getSystemBarsAppearance();
     method public int getSystemBarsBehavior();
     method public void hide(int);
-    method public default void hideInputMethod();
     method public void setSystemBarsAppearance(int, int);
     method public void setSystemBarsBehavior(int);
     method public void show(int);
-    method public default void showInputMethod();
     field public static final int APPEARANCE_LIGHT_NAVIGATION_BARS = 16; // 0x10
     field public static final int APPEARANCE_LIGHT_STATUS_BARS = 8; // 0x8
     field public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d70bf22f..ee7f6fb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3654,8 +3654,7 @@
      *
      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
      * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
-     * {@link Window#setOnContentApplyWindowInsetsListener} with {@code null} or a listener that
-     * doesn't fit the navigation bar on the window content level.
+     * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
      */
     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
 
@@ -3683,8 +3682,7 @@
      *
      * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
      * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
-     * {@link Window#setOnContentApplyWindowInsetsListener} with {@code null} or a listener that
-     * doesn't fit the status bar on the window content level.
+     * {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false}.
      */
     @Deprecated
     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
@@ -4673,7 +4671,7 @@
 
         private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
 
-        private WindowInsetsAnimationCallback mWindowInsetsAnimationCallback;
+        WindowInsetsAnimationCallback mWindowInsetsAnimationCallback;
 
         /**
          * This lives here since it's only valid for interactive views.
@@ -11537,7 +11535,7 @@
     }
 
     /**
-     * @see #PFLAG4_OPTIONAL_FITS_SYSTEM_WINDOWS
+     * @see #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
      * @hide
      */
     public void makeFrameworkOptionalFitsSystemWindows() {
@@ -11545,6 +11543,13 @@
     }
 
     /**
+     * @hide
+     */
+    public boolean isFrameworkOptionalFitsSystemWindows() {
+        return (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
+    }
+
+    /**
      * Returns the visibility status for this view.
      *
      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4f03ca1..d416d42 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7239,6 +7239,18 @@
     public void dispatchWindowInsetsAnimationPrepare(
             @NonNull InsetsAnimation animation) {
         super.dispatchWindowInsetsAnimationPrepare(animation);
+
+        // If we are root-level content view that fits insets, set dispatch mode to stop to imitate
+        // consume behavior.
+        boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
+                || isFrameworkOptionalFitsSystemWindows();
+        if (isOptionalFitSystemWindows && mAttachInfo != null
+                && getListenerInfo().mWindowInsetsAnimationCallback == null
+                && mAttachInfo.mContentOnApplyWindowInsetsListener != null) {
+            mInsetsAnimationDispatchMode = DISPATCH_MODE_STOP;
+            return;
+        }
+
         if (mInsetsAnimationDispatchMode == DISPATCH_MODE_STOP) {
             return;
         }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0ef4e33..4b284db 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -697,12 +697,10 @@
     }
 
     /**
-     * Listener for applying window insets on the content of a window in a custom way.
+     * Listener for applying window insets on the content of a window. Used only by the framework to
+     * fit content according to legacy SystemUI flags.
      *
-     * <p>Apps may choose to implement this interface if they want to apply custom policy
-     * to the way that window insets are treated for fitting root-level content views.
-     *
-     * @see Window#setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener)
+     * @hide
      */
     public interface OnContentApplyWindowInsetsListener {
 
@@ -716,13 +714,15 @@
          *
          * @param insets The root level insets that are about to be dispatched
          * @return A pair, with the first element containing the insets to apply as margin to the
-         *         root-level content views, and the second element determining what should be
-         *         dispatched to the content view.
+         * root-level content views, and the second element determining what should be
+         * dispatched to the content view.
          */
-        @NonNull Pair<Insets, WindowInsets> onContentApplyWindowInsets(
+        @NonNull
+        Pair<Insets, WindowInsets> onContentApplyWindowInsets(
                 @NonNull WindowInsets insets);
     }
 
+
     public Window(Context context) {
         mContext = context;
         mFeatures = mLocalFeatures = getDefaultFeatures(context);
@@ -1311,33 +1311,21 @@
     }
 
     /**
-     * Sets the listener to be invoked when fitting root-level content views.
+     * Sets whether the decor view should fit root-level content views for {@link WindowInsets}.
      * <p>
-     * By default, a listener that inspects the now deprecated {@link View#SYSTEM_UI_LAYOUT_FLAGS}
-     * as well the {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag is installed and
-     * fits content according to these flags.
+     * If set to {@code true}, the framework will inspect the now deprecated
+     * {@link View#SYSTEM_UI_LAYOUT_FLAGS} as well the
+     * {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag and fits content according
+     * to these flags.
      * </p>
-     * @param contentOnApplyWindowInsetsListener The listener to use for fitting root-level content
-     *                                           views, or {@code null} to disable any kind of
-     *                                           content fitting on the window level and letting the
-     *                                           {@link WindowInsets} pass through to the content
-     *                                           view.
-     * @see OnContentApplyWindowInsetsListener
-     */
-    public void setOnContentApplyWindowInsetsListener(
-            @Nullable OnContentApplyWindowInsetsListener contentOnApplyWindowInsetsListener) {
-    }
-
-    /**
-     * Resets the listener set via {@link #setOnContentApplyWindowInsetsListener} to the default
-     * state.
      * <p>
-     * By default, a listener that inspects the now deprecated {@link View#SYSTEM_UI_LAYOUT_FLAGS}
-     * as well the {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag is installed and
-     * fits content according to these flags.
+     * If set to {@code false}, the framework will not fit the content view to the insets and will
+     * just pass through the {@link WindowInsets} to the content view.
      * </p>
+     * @param decorFitsSystemWindows Whether the decor view should fit root-level content views for
+     *                               insets.
      */
-    public void resetOnContentApplyWindowInsetsListener() {
+    public void setDecorFitsSystemWindows(boolean decorFitsSystemWindows) {
     }
 
     /**
diff --git a/core/java/android/view/WindowInsetsAnimationCallback.java b/core/java/android/view/WindowInsetsAnimationCallback.java
index 1e04d02..4c8463b3 100644
--- a/core/java/android/view/WindowInsetsAnimationCallback.java
+++ b/core/java/android/view/WindowInsetsAnimationCallback.java
@@ -86,9 +86,9 @@
      * following:
      * <p>
      * <ul>
-     *     <li>Application calls {@link WindowInsetsController#hideInputMethod()},
-     *     {@link WindowInsetsController#showInputMethod()},
-     *     {@link WindowInsetsController#controlInputMethodAnimation}</li>
+     *     <li>Application calls {@link WindowInsetsController#hide(int)},
+     *     {@link WindowInsetsController#show(int)},
+     *     {@link WindowInsetsController#controlWindowInsetsAnimation}</li>
      *     <li>onPrepare is called on the view hierarchy listeners</li>
      *     <li>{@link View#onApplyWindowInsets} will be called with the end state of the
      *     animation</li>
@@ -106,12 +106,12 @@
      * related methods.
      * <p>
      * Note: If the animation is application controlled by using
-     * {@link WindowInsetsController#controlInputMethodAnimation}, the end state of the animation
+     * {@link WindowInsetsController#controlWindowInsetsAnimation}, the end state of the animation
      * is undefined as the application may decide on the end state only by passing in the
      * {@code shown} parameter when calling {@link WindowInsetsAnimationController#finish}. In this
      * situation, the system will dispatch the insets in the opposite visibility state before the
      * animation starts. Example: When controlling the input method with
-     * {@link WindowInsetsController#controlInputMethodAnimation} and the input method is currently
+     * {@link WindowInsetsController#controlWindowInsetsAnimation} and the input method is currently
      * showing, {@link View#onApplyWindowInsets} will receive a {@link WindowInsets} instance for
      * which {@link WindowInsets#isVisible} will return {@code false} for {@link Type#ime}.
      *
@@ -246,7 +246,7 @@
          * be the same as the application passed into
          * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)},
          * interpolated with the interpolator passed into
-         * {@link WindowInsetsController#controlInputMethodAnimation}.
+         * {@link WindowInsetsController#controlWindowInsetsAnimation}.
          * </p>
          * <p>
          * Note: For system-initiated animations, this will always return a valid value between 0
diff --git a/core/java/android/view/WindowInsetsAnimationControlListener.java b/core/java/android/view/WindowInsetsAnimationControlListener.java
index f91254d..701bd31 100644
--- a/core/java/android/view/WindowInsetsAnimationControlListener.java
+++ b/core/java/android/view/WindowInsetsAnimationControlListener.java
@@ -39,7 +39,7 @@
      * @param controller The controller to control the inset animation.
      * @param types The {@link InsetsType}s it was able to gain control over. Note that this may be
      *              different than the types passed into
-     *              {@link WindowInsetsController#controlInputMethodAnimation} in case the window
+     *              {@link WindowInsetsController#controlWindowInsetsAnimation} in case the window
      *              wasn't able to gain the controls because it wasn't the IME target or not
      *              currently the window that's controlling the system bars.
      */
diff --git a/core/java/android/view/WindowInsetsAnimationController.java b/core/java/android/view/WindowInsetsAnimationController.java
index 2bf0d27..4a864be 100644
--- a/core/java/android/view/WindowInsetsAnimationController.java
+++ b/core/java/android/view/WindowInsetsAnimationController.java
@@ -23,6 +23,7 @@
 import android.graphics.Insets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsAnimationCallback.AnimationBounds;
+import android.view.animation.Interpolator;
 
 /**
  * Controller for app-driven animation of system windows.
@@ -32,7 +33,7 @@
  *  synchronized, such that changes the system windows and the app's current frame
  *  are rendered at the same time.
  *  <p>
- *  Control is obtained through {@link WindowInsetsController#controlInputMethodAnimation}.
+ *  Control is obtained through {@link WindowInsetsController#controlWindowInsetsAnimation}.
  */
 @SuppressLint("NotClosable")
 public interface WindowInsetsAnimationController {
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 02323cf..f501de9 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -167,62 +167,6 @@
             @NonNull WindowInsetsAnimationControlListener listener);
 
     /**
-     * Lets the application control the animation for showing the IME in a frame-by-frame manner by
-     * modifying the position of the IME when it's causing insets.
-     *
-     * @param durationMillis Duration of the animation in
-     *                       {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or -1 if the
-     *                       animation doesn't have a predetermined duration. This value will be
-     *                       passed to {@link InsetsAnimation#getDurationMillis()}
-     * @param interpolator The interpolator used for this animation, or {@code null} if this
-     *                     animation doesn't follow an interpolation curve. This value will be
-     *                     passed to {@link InsetsAnimation#getInterpolator()} and used to calculate
-     *                     {@link InsetsAnimation#getInterpolatedFraction()}.
-     * @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the
-     *                 IME are ready to be controlled, among other callbacks.
-     *
-     * @see InsetsAnimation#getFraction()
-     * @see InsetsAnimation#getInterpolatedFraction()
-     * @see InsetsAnimation#getInterpolator()
-     * @see InsetsAnimation#getDurationMillis()
-     */
-    default void controlInputMethodAnimation(long durationMillis,
-            @Nullable Interpolator interpolator,
-            @NonNull WindowInsetsAnimationControlListener listener) {
-        controlWindowInsetsAnimation(ime(), durationMillis, interpolator, listener);
-    }
-
-    /**
-     * Makes the IME appear on screen.
-     * <p>
-     * Note that if the window currently doesn't have control over the IME, because it doesn't have
-     * focus, it will apply the change as soon as the window gains control. The app can listen to
-     * the event by observing {@link View#onApplyWindowInsets} and checking visibility with
-     * {@link WindowInsets#isVisible}.
-     *
-     * @see #controlInputMethodAnimation
-     * @see #hideInputMethod()
-     */
-    default void showInputMethod() {
-        show(ime());
-    }
-
-    /**
-     * Makes the IME disappear on screen.
-     * <p>
-     * Note that if the window currently doesn't have control over IME, because it doesn't have
-     * focus, it will apply the change as soon as the window gains control. The app can listen to
-     * the event by observing {@link View#onApplyWindowInsets} and checking visibility with
-     * {@link WindowInsets#isVisible}.
-     *
-     * @see #controlInputMethodAnimation
-     * @see #showInputMethod()
-     */
-    default void hideInputMethod() {
-        hide(ime());
-    }
-
-    /**
      * Controls the appearance of system bars.
      * <p>
      * For example, the following statement adds {@link #APPEARANCE_LIGHT_STATUS_BARS}:
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index a6450a10..dad7671 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -80,6 +80,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
+import android.view.View.OnApplyWindowInsetsListener;
 import android.view.WindowInsets.Side;
 import android.view.WindowInsets.Side.InsetsSide;
 import android.view.WindowInsets.Type;
@@ -2193,8 +2194,9 @@
          * value for {@link #softInputMode} will be ignored; the window will
          * not resize, but will stay fullscreen.
          *
-         * @deprecated Use {@link Window#setOnContentApplyWindowInsetsListener} instead with a
-         * listener that fits {@link Type#ime()} instead.
+         * @deprecated Call {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false} and
+         * install an {@link OnApplyWindowInsetsListener} on your root content view that fits insets
+         * of type {@link Type#ime()}.
          */
         @Deprecated
         public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index f13a638..5e69a5f 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -320,7 +320,8 @@
     /** @see ViewRootImpl#mActivityConfigCallback */
     private ActivityConfigCallback mActivityConfigCallback;
 
-    private OnContentApplyWindowInsetsListener mPendingOnContentApplyWindowInsetsListener;
+    private OnContentApplyWindowInsetsListener mPendingOnContentApplyWindowInsetsListener
+            = createDefaultContentWindowInsetsListener();
 
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -2109,14 +2110,9 @@
     /** Notify when decor view is attached to window and {@link ViewRootImpl} is available. */
     void onViewRootImplSet(ViewRootImpl viewRoot) {
         viewRoot.setActivityConfigCallback(mActivityConfigCallback);
-        if (mPendingOnContentApplyWindowInsetsListener != null) {
-            viewRoot.setOnContentApplyWindowInsetsListener(
-                    mPendingOnContentApplyWindowInsetsListener);
-            mPendingOnContentApplyWindowInsetsListener = null;
-        } else {
-            viewRoot.setOnContentApplyWindowInsetsListener(
-                    createDefaultContentWindowInsetsListener());
-        }
+        viewRoot.setOnContentApplyWindowInsetsListener(
+                mPendingOnContentApplyWindowInsetsListener);
+        mPendingOnContentApplyWindowInsetsListener = null;
     }
 
     private OnContentApplyWindowInsetsListener createDefaultContentWindowInsetsListener() {
@@ -3902,17 +3898,15 @@
     }
 
     @Override
-    public void setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener listener) {
+    public void setDecorFitsSystemWindows(boolean decorFitsSystemWindows) {
         ViewRootImpl impl = getViewRootImpl();
+        OnContentApplyWindowInsetsListener listener = decorFitsSystemWindows
+                ? createDefaultContentWindowInsetsListener()
+                : null;
         if (impl != null) {
             impl.setOnContentApplyWindowInsetsListener(listener);
         } else {
             mPendingOnContentApplyWindowInsetsListener = listener;
         }
     }
-
-    @Override
-    public void resetOnContentApplyWindowInsetsListener() {
-        setOnContentApplyWindowInsetsListener(createDefaultContentWindowInsetsListener());
-    }
 }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index e68c4b8..576e04f 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -432,7 +432,7 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             WindowInsetsAnimationControlListener listener =
                     mock(WindowInsetsAnimationControlListener.class);
-            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+            mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener);
 
             // Ready gets deferred until next predraw
             mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
@@ -456,7 +456,7 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             WindowInsetsAnimationControlListener listener =
                     mock(WindowInsetsAnimationControlListener.class);
-            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+            mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener);
 
             // Ready gets deferred until next predraw
             mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
@@ -476,7 +476,7 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             WindowInsetsAnimationControlListener listener =
                     mock(WindowInsetsAnimationControlListener.class);
-            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+            mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener);
 
             // Ready gets deferred until next predraw
             mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();