Add app movement for IME predictive back and adjustPan

Bug: 322836622
Flag: ACONFIG android.view.inputmethod.predictive_back_ime DISABLED
Test: separate CL
Change-Id: I671e99c14372f000fdd58b9e5a7d016ae451d70c
diff --git a/core/java/android/view/ImeBackAnimationController.java b/core/java/android/view/ImeBackAnimationController.java
index 911f7b2..ed049b5 100644
--- a/core/java/android/view/ImeBackAnimationController.java
+++ b/core/java/android/view/ImeBackAnimationController.java
@@ -18,6 +18,7 @@
 
 import static android.view.InsetsController.ANIMATION_TYPE_USER;
 import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 
@@ -60,6 +61,7 @@
     private float mLastProgress = 0f;
     private boolean mTriggerBack = false;
     private boolean mIsPreCommitAnimationInProgress = false;
+    private int mStartRootScrollY = 0;
 
     public ImeBackAnimationController(ViewRootImpl viewRoot) {
         mInsetsController = viewRoot.getInsetsController();
@@ -96,6 +98,7 @@
                     public void onReady(@NonNull WindowInsetsAnimationController controller,
                             @WindowInsets.Type.InsetsType int types) {
                         mWindowInsetsAnimationController = controller;
+                        if (isAdjustPan()) mStartRootScrollY = mViewRoot.mScrollY;
                         if (mIsPreCommitAnimationInProgress) {
                             setPreCommitProgress(mLastProgress);
                         } else {
@@ -146,6 +149,10 @@
             float imeHeight = shownY - hiddenY;
             float interpolatedProgress = BACK_GESTURE.getInterpolation(progress);
             int newY = (int) (imeHeight - interpolatedProgress * (imeHeight * PEEK_FRACTION));
+            if (mStartRootScrollY != 0) {
+                mViewRoot.setScrollY(
+                        (int) (mStartRootScrollY * (1 - interpolatedProgress * PEEK_FRACTION)));
+            }
             mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, newY), 1f,
                     progress);
         }
@@ -199,6 +206,19 @@
             mInsetsController.setPredictiveBackImeHideAnimInProgress(true);
             notifyHideIme();
         }
+        if (mStartRootScrollY != 0) {
+            // RootView is panned, ensure that it is scrolled back to the intended scroll position
+            if (triggerBack) {
+                // requesting ime as invisible
+                mInsetsController.setRequestedVisibleTypes(0, ime());
+                // changes the animation state and notifies RootView of changed insets, which
+                // causes it to reset its scrollY to 0f (animated)
+                mInsetsController.onAnimationStateChanged(ime(), /*running*/ true);
+            } else {
+                // This causes RootView to update its scroll back to the panned position
+                mInsetsController.getHost().notifyInsetsChanged();
+            }
+        }
     }
 
     private void notifyHideIme() {
@@ -222,6 +242,7 @@
         mTriggerBack = false;
         mIsPreCommitAnimationInProgress = false;
         mInsetsController.setPredictiveBackImeHideAnimInProgress(false);
+        mStartRootScrollY = 0;
     }
 
     private void resetPostCommitAnimator() {
@@ -236,6 +257,11 @@
                 == SOFT_INPUT_ADJUST_RESIZE;
     }
 
+    private boolean isAdjustPan() {
+        return (mViewRoot.mWindowAttributes.softInputMode & SOFT_INPUT_MASK_ADJUST)
+                == SOFT_INPUT_ADJUST_PAN;
+    }
+
     private boolean isHideAnimationInProgress() {
         return mPostCommitAnimator != null && mTriggerBack;
     }
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 3def604..62dbc39 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -66,7 +66,12 @@
                     "ImeInsetsSourceConsumer#onAnimationFinished",
                     mController.getHost().getInputMethodManager(), null /* icProto */);
         }
-        final boolean insetsChanged = super.onAnimationStateChanged(running);
+        boolean insetsChanged = super.onAnimationStateChanged(running);
+        if (running && !isShowRequested() && mController.isPredictiveBackImeHideAnimInProgress()) {
+            // IME predictive back animation switched from pre-commit to post-commit.
+            insetsChanged |= applyLocalVisibilityOverride();
+        }
+
         if (!isShowRequested()) {
             mIsRequestedVisibleAwaitingLeash = false;
             if (!running && !mHasPendingRequest) {
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 8c00fbb..6c90011 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -1620,7 +1620,7 @@
         onAnimationStateChanged(removedTypes, false /* running */);
     }
 
-    private void onAnimationStateChanged(@InsetsType int types, boolean running) {
+    void onAnimationStateChanged(@InsetsType int types, boolean running) {
         boolean insetsChanged = false;
         for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
             final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cd0602c..00840cc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5881,6 +5881,13 @@
         return handled;
     }
 
+    void setScrollY(int scrollY) {
+        if (mScroller != null) {
+            mScroller.abortAnimation();
+        }
+        mScrollY = scrollY;
+    }
+
     /**
      * @hide
      */