Fixes for floating search bar (e.g. background protection).

 - Adds background protection for the search bar
 - Views animating based on keyboard now support manual swipes.

Bug: 213954333
Bug: 259004115
Bug: 251460671
Test: Manual
Change-Id: I055766126fb46a8e8b48907e442c9e54aaa4badf
diff --git a/res/layout/all_apps_content.xml b/res/layout/all_apps_content.xml
index b33029f..773ab8d 100644
--- a/res/layout/all_apps_content.xml
+++ b/res/layout/all_apps_content.xml
@@ -44,6 +44,13 @@
 
     </com.android.launcher3.allapps.FloatingHeaderView>
 
+    <View
+        android:id="@+id/search_protection"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone"
+        android:forceHasOverlappingRendering="false" />
+
     <include layout="@layout/search_container_all_apps" />
 
     <include layout="@layout/all_apps_fast_scroller" />
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index e4e56a9..5c55b53 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -282,7 +282,7 @@
     @Override
     public int getHeaderBottom() {
         if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
-            return super.getHeaderBottom();
+            return super.getHeaderBottom() + mHeader.getClipTop();
         }
         return super.getHeaderBottom() + mSearchContainer.getBottom();
     }
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 8e519c1..f308a25 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -58,6 +58,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.keyboard.FocusedItemDecorator;
 import com.android.launcher3.model.StringCache;
 import com.android.launcher3.model.data.ItemInfo;
@@ -123,6 +124,7 @@
     protected FloatingHeaderView mHeader;
     private View mBottomSheetBackground;
     private View mBottomSheetHandleArea;
+    @Nullable private View mSearchBarProtection;
 
     protected boolean mUsingTabs;
     private boolean mHasWorkApps;
@@ -363,6 +365,11 @@
         return mSearchRecyclerView;
     }
 
+    @Nullable
+    public View getSearchBarProtection() {
+        return mSearchBarProtection;
+    }
+
     protected boolean isPersonalTab() {
         return mViewPager == null || mViewPager.getNextPage() == 0;
     }
@@ -410,6 +417,12 @@
         });
 
         mHeader = findViewById(R.id.all_apps_header);
+        mSearchBarProtection = findViewById(R.id.search_protection);
+        if (mSearchBarProtection != null) {
+            mSearchBarProtection.setBackgroundColor(mScrimColor);
+            mSearchBarProtection.setVisibility(
+                    FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get() ? VISIBLE : GONE);
+        }
         mSearchRecyclerView = findViewById(R.id.search_results_list_view);
         mAH.get(AdapterHolder.SEARCH).setup(mSearchRecyclerView,
                 /* Filter out A-Z apps */ itemInfo -> false);
@@ -744,7 +757,7 @@
         if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
             int bottom = getHeaderBottom();
             FloatingHeaderView headerView = getFloatingHeaderView();
-            if (!mUsingTabs) {
+            if (!mUsingTabs && !FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
                 // Add protection which is otherwise added when tabs scroll up.
                 bottom += headerView.getTabsAdditionalPaddingTop();
             }
@@ -803,17 +816,6 @@
         return mActivityContext.getDeviceProfile().isTablet ? mBottomSheetBackground : this;
     }
 
-    /**
-     * Sets whether the view or its children should react to the window inset.
-     * Used for when exiting all apps -> workspace and determines if window inset
-     * should be applied.. ex) the work mode switch.
-     */
-    public void setApplyWindowInset(boolean shouldApplyWindowInset) {
-        if (mWorkManager.getWorkModeSwitch() != null) {
-            mWorkManager.getWorkModeSwitch().setApplyWindowInset(shouldApplyWindowInset);
-        }
-    }
-
     protected void onInitializeRecyclerView(RecyclerView rv) {
         rv.addOnScrollListener(mScrollListener);
     }
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 1cbb0f9..7fd3752 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -364,6 +364,10 @@
         onHeightUpdated();
     }
 
+    public int getClipTop() {
+        return mHeaderClip.top;
+    }
+
     public void reset(boolean animate) {
         if (mAnimator.isStarted()) {
             mAnimator.cancel();
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index 2272cdc..aadd0b5 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -19,7 +19,6 @@
 import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
 
 import android.content.Context;
-import android.graphics.Insets;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
@@ -27,6 +26,9 @@
 import android.view.WindowInsets;
 import android.widget.Button;
 
+import androidx.core.graphics.Insets;
+import androidx.core.view.WindowInsetsCompat;
+
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
@@ -49,10 +51,10 @@
     private static final int FLAG_PROFILE_TOGGLE_ONGOING = 1 << 3;
 
     private final Rect mInsets = new Rect();
+    private final Rect mImeInsets = new Rect();
     private int mFlags;
     private boolean mWorkEnabled;
     private boolean mOnWorkTab;
-    private boolean mApplyWindowInset;
 
     public WorkModeSwitch(Context context) {
         this(context, null, 0);
@@ -89,12 +91,12 @@
     @Override
     public void setInsets(Rect insets) {
         mInsets.set(insets);
+        updateTranslationY();
         MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
         if (lp != null) {
             int bottomMargin = getResources().getDimensionPixelSize(R.dimen.work_fab_margin_bottom);
             DeviceProfile dp = ActivityContext.lookupContext(getContext()).getDeviceProfile();
             if (FeatureFlags.ENABLE_FLOATING_SEARCH_BAR.get()) {
-                bottomMargin <<= 1;  // Double margin to add space above search bar.
                 bottomMargin += dp.hotseatQsbHeight;
             }
 
@@ -154,7 +156,6 @@
 
     private void updateVisibility() {
         clearAnimation();
-        onApplyWindowInsets(getRootWindowInsets());
         if (mWorkEnabled && mOnWorkTab) {
             setFlag(FLAG_FADE_ONGOING);
             setVisibility(VISIBLE);
@@ -170,16 +171,29 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        if (!Utilities.ATLEAST_R || !mApplyWindowInset) {
-            return insets;
-        }
-        if (insets.isVisible(WindowInsets.Type.ime())) {
-            Insets keyboardInsets = insets.getInsets(WindowInsets.Type.ime());
-            setTranslationY(mInsets.bottom - keyboardInsets.bottom);
+        WindowInsetsCompat windowInsetsCompat =
+                WindowInsetsCompat.toWindowInsetsCompat(insets, this);
+        if (windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime())) {
+            setInsets(mImeInsets, windowInsetsCompat.getInsets(WindowInsetsCompat.Type.ime()));
         } else {
-            setTranslationY(0);
+            mImeInsets.setEmpty();
         }
-        return insets;
+        updateTranslationY();
+        return super.onApplyWindowInsets(insets);
+    }
+
+    private void updateTranslationY() {
+        setTranslationY(-mImeInsets.bottom);
+    }
+
+    @Override
+    public void setTranslationY(float translationY) {
+        // Always translate at least enough for nav bar insets.
+        super.setTranslationY(Math.min(translationY, -mInsets.bottom));
+    }
+
+    private void setInsets(Rect rect, Insets insets) {
+        rect.set(insets.left, insets.top, insets.right, insets.bottom);
     }
 
     @Override
@@ -199,8 +213,4 @@
     private void removeFlag(int flag) {
         mFlags &= ~flag;
     }
-
-    public void setApplyWindowInset(boolean applyWindowInset){
-        mApplyWindowInset = applyWindowInset;
-    }
 }
diff --git a/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java b/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java
index 9d96365..3863dc1 100644
--- a/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java
+++ b/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java
@@ -53,10 +53,21 @@
             mView.setTranslationY(mInitialTranslation);
             return windowInsets;
         }
-        float progress = list.get(0).getInterpolatedFraction();
+        WindowInsetsAnimation animation = list.get(0);
 
-        mView.setTranslationY(
-                Utilities.mapRange(progress, mInitialTranslation, mTerminalTranslation));
+        if (animation.getDurationMillis() > -1) {
+            float progress = animation.getInterpolatedFraction();
+            mView.setTranslationY(
+                    Utilities.mapRange(progress, mInitialTranslation, mTerminalTranslation));
+        } else {
+            // Manually controlled animation: Set translation to keyboard height.
+            int translationY = -windowInsets.getInsets(WindowInsets.Type.ime()).bottom;
+            if (mView.getParent() instanceof View) {
+                // Offset any translation of the parent (e.g. All Apps parallax).
+                translationY -= ((View) mView.getParent()).getTranslationY();
+            }
+            mView.setTranslationY(translationY);
+        }
 
         return windowInsets;
     }
@@ -73,6 +84,7 @@
 
     @Override
     public void onEnd(WindowInsetsAnimation animation) {
+        mView.setTranslationY(mTerminalTranslation);
         if (mView instanceof KeyboardInsetListener) {
             ((KeyboardInsetListener) mView).onTranslationEnd();
         }