Merge "Making tablet grid scalable and tuning size" into tm-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index 4127650..cf854ed 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -121,7 +121,7 @@
   optional int32 cardinality = 2;
 }
 
-// Next value 39
+// Next value 40
 enum Attribute {
   UNKNOWN = 0;
   DEFAULT_LAYOUT = 1;       // icon automatically placed in workspace, folder, hotseat
@@ -166,6 +166,9 @@
   ALL_APPS_SEARCH_RESULT_LEGACY_SHORTCUT = 30;
   ALL_APPS_SEARCH_RESULT_ASSISTANT_MEMORY = 31;
 
+  // Web suggestions provided by AGA
+  ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39;
+
   // Suggestion Type provided by AGA
   WEB_SEARCH_RESULT_QUERY = 32;
   WEB_SEARCH_RESULT_TRENDING = 33;
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 3f29e43..5c66944 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -18,6 +18,7 @@
 import static android.app.prediction.AppTargetEvent.ACTION_DISMISS;
 import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH;
 import static android.app.prediction.AppTargetEvent.ACTION_PIN;
+import static android.app.prediction.AppTargetEvent.ACTION_UNDISMISS;
 import static android.app.prediction.AppTargetEvent.ACTION_UNPIN;
 
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
@@ -25,6 +26,7 @@
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
 import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED;
@@ -176,6 +178,8 @@
                     mContext.getPackageName(), Process.myUserHandle())
                     .build();
             sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
+        } else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) {
+            sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 1c6d4a2..296000b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -785,5 +785,6 @@
         pw.println(String.format(
                 "%s\tmBindInProgress=%b", prefix, mBindingItems));
         mControllers.dumpLogs(prefix + "\t", pw);
+        mDeviceProfile.dump(prefix, pw);
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index f93917f..27a55c3 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -25,11 +25,8 @@
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
 import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
 import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.LINEAR_TELEPORT;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
 
 import android.view.MotionEvent;
 
@@ -140,7 +137,6 @@
         builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL,
                 ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
                 ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
-        builder.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
         return builder;
     }
 
@@ -155,7 +151,6 @@
         builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
                 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
                 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
-        builder.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
         return builder;
     }
 
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index a62e9d1..ed81d7e 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -21,8 +21,10 @@
 import static com.android.launcher3.GestureNavContract.EXTRA_GESTURE_CONTRACT;
 import static com.android.launcher3.GestureNavContract.EXTRA_ICON_POSITION;
 import static com.android.launcher3.GestureNavContract.EXTRA_ICON_SURFACE;
+import static com.android.launcher3.GestureNavContract.EXTRA_ON_FINISH_CALLBACK;
 import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK;
 import static com.android.launcher3.Utilities.createHomeIntent;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
 import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
 
@@ -44,7 +46,9 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.ParcelUuid;
+import android.os.RemoteException;
 import android.os.UserHandle;
+import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
@@ -82,6 +86,8 @@
 public class FallbackSwipeHandler extends
         AbsSwipeUpHandler<RecentsActivity, FallbackRecentsView, RecentsState> {
 
+    private static final String TAG = "FallbackSwipeHandler";
+
     /**
      * Message used for receiving gesture nav contract information. We use a static messenger to
      * avoid leaking too make binders in case the receiving launcher does not handle the contract
@@ -224,7 +230,8 @@
         }
     }
 
-    private class FallbackHomeAnimationFactory extends HomeAnimationFactory {
+    private class FallbackHomeAnimationFactory extends HomeAnimationFactory
+            implements Consumer<Message> {
         private final Rect mTempRect = new Rect();
         private final TransformParams mHomeAlphaParams = new TransformParams();
         private final AnimatedFloat mHomeAlpha;
@@ -235,6 +242,9 @@
         private final RectF mTargetRect = new RectF();
         private SurfaceControl mSurfaceControl;
 
+        private boolean mAnimationFinished;
+        private Message mOnFinishCallback;
+
         private final long mDuration;
 
         private RectFSpringAnim mSpringAnim;
@@ -336,9 +346,26 @@
         @Override
         public void setAnimation(RectFSpringAnim anim) {
             mSpringAnim = anim;
+            mSpringAnim.addAnimatorListener(forEndCallback(this::onRectAnimationEnd));
         }
 
-        private void onMessageReceived(Message msg) {
+        private void onRectAnimationEnd() {
+            mAnimationFinished = true;
+            maybeSendEndMessage();
+        }
+
+        private void maybeSendEndMessage() {
+            if (mAnimationFinished && mOnFinishCallback != null) {
+                try {
+                    mOnFinishCallback.replyTo.send(mOnFinishCallback);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error sending icon position", e);
+                }
+            }
+        }
+
+        @Override
+        public void accept(Message msg) {
             try {
                 Bundle data = msg.getData();
                 RectF position = data.getParcelable(EXTRA_ICON_POSITION);
@@ -348,7 +375,9 @@
                     if (mSpringAnim != null) {
                         mSpringAnim.onTargetPositionChanged();
                     }
+                    mOnFinishCallback = data.getParcelable(EXTRA_ON_FINISH_CALLBACK);
                 }
+                maybeSendEndMessage();
             } catch (Exception e) {
                 // Ignore
             }
@@ -382,8 +411,8 @@
                 Bundle gestureNavContract = new Bundle();
                 gestureNavContract.putParcelable(EXTRA_COMPONENT_NAME, key.getComponent());
                 gestureNavContract.putParcelable(EXTRA_USER, UserHandle.of(key.userId));
-                gestureNavContract.putParcelable(EXTRA_REMOTE_CALLBACK,
-                        sMessageReceiver.newCallback(this::onMessageReceived));
+                gestureNavContract.putParcelable(
+                        EXTRA_REMOTE_CALLBACK, sMessageReceiver.newCallback(this));
                 intent.putExtra(EXTRA_GESTURE_CONTRACT, gestureNavContract);
             }
         }
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index f1ace49..7ad60bb 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -63,7 +63,6 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.MotionEvent;
-import android.view.Surface;
 
 import androidx.annotation.BinderThread;
 
@@ -557,8 +556,7 @@
         if (mIsOneHandedModeEnabled) {
             final Info displayInfo = mDisplayController.getInfo();
             return (mRotationTouchHelper.touchInOneHandedModeRegion(ev)
-                && displayInfo.rotation != Surface.ROTATION_90
-                && displayInfo.rotation != Surface.ROTATION_270);
+                    && (displayInfo.currentSize.x < displayInfo.currentSize.y));
         }
         return false;
     }
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 53296b5..3206825 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -962,10 +962,10 @@
             RecentsModel.INSTANCE.get(this).dump("", pw);
             pw.println("ProtoTrace:");
             pw.println("  file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
-            mTaskbarManager.dumpLogs("", pw);
             if (createdOverviewActivity != null) {
                 createdOverviewActivity.getDeviceProfile().dump("", pw);
             }
+            mTaskbarManager.dumpLogs("", pw);
         }
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 8a62c14..ca6712f 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -58,7 +58,6 @@
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.FailureWatcher;
 import com.android.launcher3.util.rule.ScreenRecordRule;
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.quickstep.views.RecentsView;
 
 import org.junit.After;
@@ -167,7 +166,6 @@
     // b/143488140
     //@NavigationModeSwitch
     @Test
-    @ScreenRecord // b/223278795
     public void goToOverviewFromHome() {
         mDevice.pressHome();
         assertTrue("Fallback Launcher not visible", mDevice.wait(Until.hasObject(By.pkg(
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
index 1517087..73200de 100644
--- a/res/layout/work_apps_edu.xml
+++ b/res/layout/work_apps_edu.xml
@@ -19,37 +19,49 @@
     android:layout_marginTop="8dp"
     android:gravity="center">
 
-    <LinearLayout
+    <RelativeLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:paddingHorizontal="@dimen/work_card_padding_horizontal"
-        android:paddingVertical="@dimen/work_card_padding_horizontal"
+        android:orientation="horizontal"
         android:background="@drawable/work_card"
         android:layout_gravity="center_horizontal"
-        android:gravity="center"
+        android:paddingEnd="@dimen/work_card_margin"
+        android:paddingStart="@dimen/work_card_margin"
+        android:paddingTop="@dimen/work_card_margin"
         android:id="@+id/wrapper">
-
         <TextView
             style="@style/PrimaryHeadline"
             android:textColor="?android:attr/textColorPrimary"
             android:id="@+id/work_apps_paused_title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="@dimen/work_card_padding_horizontal"
+            android:layout_marginBottom="@dimen/work_card_margin"
+            android:layout_marginRight="@dimen/work_card_margin"
             android:text="@string/work_profile_edu_work_apps"
-            android:textAlignment="center"
-            android:textSize="20sp" />
-
-        <Button
+            android:textSize="18sp" />
+        <RelativeLayout
             android:layout_width="match_parent"
-            android:layout_height="@dimen/work_card_button_height"
-            android:id="@+id/action_btn"
-            android:textColor="?attr/workProfileOverlayTextColor"
-            android:text="@string/work_profile_edu_accept"
-            android:textAlignment="center"
-            android:background="@drawable/rounded_action_button"
+            android:layout_height="@dimen/padded_rounded_button_height"
+            android:orientation="horizontal"
+            >
+            <FrameLayout
+                android:layout_width="@dimen/rounded_button_width"
+                android:layout_height="@dimen/rounded_button_width"
+                android:background="@drawable/rounded_action_button"
+                android:padding="@dimen/rounded_button_padding"
+                android:layout_alignParentRight="true">
+                <ImageButton
+                    android:layout_width="@dimen/x_icon_size"
+                    android:layout_height="@dimen/x_icon_size"
+                    android:id="@+id/action_btn"
+                    android:src="@drawable/ic_remove_no_shadow"
+                    android:layout_gravity="center"
+                    android:padding="@dimen/x_icon_padding" />
+            </FrameLayout>
+        </RelativeLayout>
 
-            android:textSize="14sp" />
-    </LinearLayout>
+    </RelativeLayout>
+
+
+
 </com.android.launcher3.allapps.WorkEduCard>
\ No newline at end of file
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index 04faa15..c536d77 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -29,4 +29,6 @@
     android:drawableStart="@drawable/ic_corp_off"
     android:layout_marginBottom="@dimen/work_fab_margin"
     android:layout_marginEnd="@dimen/work_fab_margin"
+    android:paddingLeft="@dimen/work_mode_fab_padding"
+    android:paddingRight="@dimen/work_mode_fab_padding"
     android:text="@string/work_apps_pause_btn_text" />
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 327174d..b320bb2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -137,18 +137,25 @@
 
 <!-- Floating action button inside work tab to toggle work profile -->
     <dimen name="work_fab_height">56dp</dimen>
-    <dimen name="work_fab_radius">28dp</dimen>
-    <dimen name="work_card_padding_horizontal">24dp</dimen>
+    <dimen name="work_fab_radius">16dp</dimen>
+    <dimen name="work_card_padding_horizontal">10dp</dimen>
     <dimen name="work_card_button_height">52dp</dimen>
     <dimen name="work_fab_margin">16dp</dimen>
+    <dimen name="work_mode_fab_padding">16dp</dimen>
     <dimen name="work_profile_footer_padding">20dp</dimen>
     <dimen name="work_edu_card_margin">16dp</dimen>
-    <dimen name="work_edu_card_radius">28dp</dimen>
+    <dimen name="work_edu_card_radius">16dp</dimen>
+
+    <dimen name="work_card_margin">24dp</dimen>
+    <!-- (x) icon button inside work edu card -->
+    <dimen name="rounded_button_width">24dp</dimen>
+    <dimen name="x_icon_size">16dp</dimen>
+    <dimen name="x_icon_padding">4dp</dimen>
 
     <!-- rounded button shown inside card views, and snack bars  -->
     <dimen name="padded_rounded_button_height">48dp</dimen>
-    <dimen name="rounded_button_height">32dp</dimen>
-    <dimen name="rounded_button_radius">16dp</dimen>
+    <dimen name="rounded_button_height">48dp</dimen>
+    <dimen name="rounded_button_radius">200dp</dimen>
     <dimen name="rounded_button_padding">8dp</dimen>
 
 
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 500244c..72d0f59 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -250,6 +250,7 @@
         windowX = windowBounds.bounds.left;
         windowY = windowBounds.bounds.top;
         this.rotationHint = windowBounds.rotationHint;
+        mInsets.set(windowBounds.insets);
 
         isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
 
@@ -302,7 +303,7 @@
         desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
         desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
 
-        bottomSheetTopPadding = windowBounds.insets.top // statusbar height
+        bottomSheetTopPadding = mInsets.top // statusbar height
                 + res.getDimensionPixelSize(R.dimen.bottom_sheet_extra_top_padding)
                 + (isTablet ? 0 : edgeMarginPx); // phones need edgeMarginPx additional padding
 
@@ -569,6 +570,7 @@
         WindowBounds bounds = new WindowBounds(
                 widthPx, heightPx, availableWidthPx, availableHeightPx, rotationHint);
         bounds.bounds.offsetTo(windowX, windowY);
+        bounds.insets.set(mInsets);
         return new Builder(context, inv, mInfo)
                 .setWindowBounds(bounds)
                 .setUseTwoPanels(isTwoPanels)
@@ -1192,9 +1194,12 @@
         writer.println(prefix + pxToDpStr("windowY", windowY));
         writer.println(prefix + pxToDpStr("widthPx", widthPx));
         writer.println(prefix + pxToDpStr("heightPx", heightPx));
-
         writer.println(prefix + pxToDpStr("availableWidthPx", availableWidthPx));
         writer.println(prefix + pxToDpStr("availableHeightPx", availableHeightPx));
+        writer.println(prefix + pxToDpStr("mInsets.left", mInsets.left));
+        writer.println(prefix + pxToDpStr("mInsets.top", mInsets.top));
+        writer.println(prefix + pxToDpStr("mInsets.right", mInsets.right));
+        writer.println(prefix + pxToDpStr("mInsets.bottom", mInsets.bottom));
 
         writer.println(prefix + "\taspectRatio:" + aspectRatio);
 
@@ -1240,6 +1245,10 @@
         writer.println(prefix + pxToDpStr("folderCellLayoutBorderSpacePx Vertical",
                 folderCellLayoutBorderSpacePx.y));
 
+        writer.println(prefix + pxToDpStr("bottomSheetTopPadding", bottomSheetTopPadding));
+
+        writer.println(prefix + pxToDpStr("allAppsShiftRange", allAppsShiftRange));
+        writer.println(prefix + pxToDpStr("allAppsTopPadding", allAppsTopPadding));
         writer.println(prefix + pxToDpStr("allAppsIconSizePx", allAppsIconSizePx));
         writer.println(prefix + pxToDpStr("allAppsIconTextSizePx", allAppsIconTextSizePx));
         writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
diff --git a/src/com/android/launcher3/GestureNavContract.java b/src/com/android/launcher3/GestureNavContract.java
index 2a7e629..c782dca 100644
--- a/src/com/android/launcher3/GestureNavContract.java
+++ b/src/com/android/launcher3/GestureNavContract.java
@@ -18,20 +18,30 @@
 import static android.content.Intent.EXTRA_COMPONENT_NAME;
 import static android.content.Intent.EXTRA_USER;
 
+import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE;
+
 import android.annotation.TargetApi;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.RectF;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
+import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.SurfaceControl;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.views.ActivityContext;
+
+import java.lang.ref.WeakReference;
+
 /**
  * Class to encapsulate the handshake protocol between Launcher and gestureNav.
  */
@@ -43,6 +53,7 @@
     public static final String EXTRA_ICON_POSITION = "gesture_nav_contract_icon_position";
     public static final String EXTRA_ICON_SURFACE = "gesture_nav_contract_surface_control";
     public static final String EXTRA_REMOTE_CALLBACK = "android.intent.extra.REMOTE_CALLBACK";
+    public static final String EXTRA_ON_FINISH_CALLBACK = "gesture_nav_contract_finish_callback";
 
     public final ComponentName componentName;
     public final UserHandle user;
@@ -59,10 +70,15 @@
      * Sends the position information to the receiver
      */
     @TargetApi(Build.VERSION_CODES.R)
-    public void sendEndPosition(RectF position, @Nullable SurfaceControl surfaceControl) {
+    public void sendEndPosition(RectF position, ActivityContext context,
+            @Nullable SurfaceControl surfaceControl) {
         Bundle result = new Bundle();
         result.putParcelable(EXTRA_ICON_POSITION, position);
         result.putParcelable(EXTRA_ICON_SURFACE, surfaceControl);
+        if (sMessageReceiver == null) {
+            sMessageReceiver = new StaticMessageReceiver();
+        }
+        result.putParcelable(EXTRA_ON_FINISH_CALLBACK, sMessageReceiver.setCurrentContext(context));
 
         Message callback = Message.obtain();
         callback.copyFrom(mCallback);
@@ -98,4 +114,42 @@
         }
         return null;
     }
+
+    /**
+     * Message used for receiving gesture nav contract information. We use a static messenger to
+     * avoid leaking too make binders in case the receiving launcher does not handle the contract
+     * properly.
+     */
+    private static StaticMessageReceiver sMessageReceiver = null;
+
+    private static class StaticMessageReceiver implements Handler.Callback {
+
+        private static final int MSG_CLOSE_LAST_TARGET = 0;
+
+        private final Messenger mMessenger =
+                new Messenger(new Handler(Looper.getMainLooper(), this));
+
+        private WeakReference<ActivityContext> mLastTarget = new WeakReference<>(null);
+
+        public Message setCurrentContext(ActivityContext context) {
+            mLastTarget = new WeakReference<>(context);
+
+            Message msg = Message.obtain();
+            msg.replyTo = mMessenger;
+            msg.what = MSG_CLOSE_LAST_TARGET;
+            return msg;
+        }
+
+        @Override
+        public boolean handleMessage(@NonNull Message message) {
+            if (message.what == MSG_CLOSE_LAST_TARGET) {
+                ActivityContext lastContext = mLastTarget.get();
+                if (lastContext != null) {
+                    AbstractFloatingView.closeOpenViews(lastContext, false, TYPE_ICON_SURFACE);
+                }
+                return true;
+            }
+            return false;
+        }
+    }
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1cead11..2636d55 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -604,7 +604,13 @@
     public void onEnterAnimationComplete() {
         super.onEnterAnimationComplete();
         mRotationHelper.setCurrentTransitionRequest(REQUEST_NONE);
-        AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
+        // Starting with Android S, onEnterAnimationComplete is sent immediately
+        // causing the surface to get removed before the animation completed (b/175345344).
+        // Instead we rely on next user touch event to remove the view and optionally a callback
+        // from system from Android T onwards.
+        if (!Utilities.ATLEAST_S) {
+            AbstractFloatingView.closeOpenViews(this, false, TYPE_ICON_SURFACE);
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index c43172c..4f3ae59 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -38,6 +38,7 @@
 
     // Progress after which the transition is assumed to be a success
     public static final float SUCCESS_TRANSITION_PROGRESS = 0.5f;
+    public static final float TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS = 0.3f;
 
     public static final IntProperty<Drawable> DRAWABLE_ALPHA =
             new IntProperty<Drawable>("drawableAlpha") {
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index cd06414..5b037e4 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -8,6 +8,7 @@
 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DISMISS_PREDICTION;
 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE;
 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_UNINSTALL;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_UNINSTALL_CANCELLED;
@@ -46,6 +47,7 @@
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.PendingRequestArgs;
+import com.android.launcher3.views.Snackbar;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 
 import java.net.URISyntaxException;
@@ -220,7 +222,8 @@
 
     @Override
     public void completeDrop(final DragObject d) {
-        ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo);
+        ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo,
+                d.logInstanceId);
         if (d.dragSource instanceof DeferredOnComplete) {
             DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
             if (target != null) {
@@ -264,7 +267,7 @@
      * Performs the drop action and returns the target component for the dragObject or null if
      * the action was not performed.
      */
-    protected ComponentName performDropAction(View view, ItemInfo info) {
+    protected ComponentName performDropAction(View view, ItemInfo info, InstanceId instanceId) {
         if (mCurrentAccessibilityAction == RECONFIGURE) {
             int widgetId = getReconfigurableWidgetId(view);
             if (widgetId != INVALID_APPWIDGET_ID) {
@@ -276,7 +279,16 @@
             return null;
         }
         if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
-            // We sent the log event, nothing else left to do
+            if (FeatureFlags.ENABLE_DISMISS_PREDICTION_UNDO.get()) {
+                mLauncher.getDragLayer()
+                        .announceForAccessibility(getContext().getString(R.string.item_removed));
+                Snackbar.show(mLauncher, R.string.item_removed, R.string.undo, () -> { }, () -> {
+                    mStatsLogManager.logger()
+                            .withInstanceId(instanceId)
+                            .withItemInfo(info)
+                            .log(LAUNCHER_DISMISS_PREDICTION_UNDO);
+                });
+            }
             return null;
         }
         // else: mCurrentAccessibilityAction == UNINSTALL
@@ -303,8 +315,9 @@
 
     @Override
     public void onAccessibilityDrop(View view, ItemInfo item) {
-        doLog(new InstanceIdSequence().newInstanceId(), item);
-        performDropAction(view, item);
+        InstanceId instanceId = new InstanceIdSequence().newInstanceId();
+        doLog(instanceId, item);
+        performDropAction(view, item, instanceId);
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/WorkAdapterProvider.java b/src/com/android/launcher3/allapps/WorkAdapterProvider.java
index f52a21f..ce44958 100644
--- a/src/com/android/launcher3/allapps/WorkAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/WorkAdapterProvider.java
@@ -92,8 +92,6 @@
         TextView title = view.findViewById(R.id.work_apps_paused_title);
         title.setText(cache.workProfileEdu);
 
-        Button button = view.findViewById(R.id.action_btn);
-        button.setText(cache.workProfileEduAccept);
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index a6a47a7..886460e 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.allapps.search;
 
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME;
 
 import android.text.Editable;
 import android.text.SpannableStringBuilder;
@@ -122,7 +123,9 @@
 
         if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_GO) {
             mLauncher.getStatsLogManager().logger()
-                    .log(LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME);
+                    .log(actionId == EditorInfo.IME_ACTION_SEARCH
+                            ? LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME
+                            : LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME);
             // selectFocusedView should return SearchTargetEvent that is passed onto onClick
             return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
         }
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 9c12abd..1e7b224 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -130,23 +130,6 @@
         }
     };
 
-    public static final Interpolator LINEAR_TELEPORT = t -> {
-        float startTeleport = 0.2f;
-        float endTeleport = 0.4f;
-        float teleportProgress = 0.5f;
-        float v;
-        if (t < startTeleport) {
-            v = LINEAR.getInterpolation(t);
-        } else if (t < endTeleport) {
-            v = Utilities.mapToRange(t, startTeleport, endTeleport, startTeleport,
-                    endTeleport + teleportProgress, ACCEL_DEACCEL);
-        } else {
-            v = LINEAR.getInterpolation(t) + teleportProgress;
-        }
-        v = Utilities.boundToRange(v, 0f, 1f);
-        return v;
-    };
-
     private static final float FAST_FLING_PX_MS = 10;
 
     public static Interpolator scrollInterpolatorForVelocity(float velocity) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 420180b..626e15c 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -265,6 +265,10 @@
             "USE_LOCAL_ICON_OVERRIDES", true,
             "Use inbuilt monochrome icons if app doesn't provide one");
 
+    public static final BooleanFlag ENABLE_DISMISS_PREDICTION_UNDO = getDebugFlag(
+            "ENABLE_DISMISS_PREDICTION_UNDO", false,
+            "Show an 'Undo' snackbar when users dismiss a predicted hotseat item");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index b8ecec1..9af72c3 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -579,7 +579,14 @@
         LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS(1010),
 
         @UiEvent(doc = "User tapped taskbar a11y button")
-        LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS(1011);
+        LAUNCHER_TASKBAR_A11Y_BUTTON_LONGPRESS(1011),
+
+        @UiEvent(doc = "Show an 'Undo' snackbar when users dismiss a predicted hotseat item")
+        LAUNCHER_DISMISS_PREDICTION_UNDO(1035),
+
+        @UiEvent(doc = "User clicked on IME quicksearch button.")
+        LAUNCHER_ALLAPPS_QUICK_SEARCH_WITH_IME(1047),
+        ;
 
         // ADD MORE
 
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index c00e174..a125fbe 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.touch;
 
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
@@ -285,8 +286,13 @@
                             ? mToState : mFromState;
             // snap to top or bottom using the release velocity
         } else {
+            float successTransitionProgress =
+                    mLauncher.getDeviceProfile().isTablet
+                            && (mToState == ALL_APPS || mFromState == ALL_APPS)
+                            ? TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS
+                            : SUCCESS_TRANSITION_PROGRESS;
             targetState =
-                    (interpolatedProgress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
+                    (interpolatedProgress > successTransitionProgress) ? mToState : mFromState;
         }
 
         final float endProgress;
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index f7d3492..5aac3f3 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -20,10 +20,8 @@
 import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
 import static com.android.launcher3.anim.Interpolators.INSTANT;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.LINEAR_TELEPORT;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
 
 import android.view.MotionEvent;
 import android.view.animation.Interpolator;
@@ -113,7 +111,6 @@
         config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
         config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
                 ? FINAL_FRAME : ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
-        config.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
     }
 
     /**
@@ -125,7 +122,6 @@
         config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
         config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
                 ? INSTANT : ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
-        config.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
     }
 
 
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 5d88884..ed31e8d 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -17,6 +17,8 @@
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
+import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
+import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
 
 import android.animation.Animator;
@@ -184,7 +186,10 @@
 
     @Override
     public void onDragEnd(float velocity) {
-        if ((mSwipeDetector.isFling(velocity) && velocity > 0) || mTranslationShift > 0.5f) {
+        float successfulShiftThreshold = mActivityContext.getDeviceProfile().isTablet
+                ? TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS : SUCCESS_TRANSITION_PROGRESS;
+        if ((mSwipeDetector.isFling(velocity) && velocity > 0)
+                || mTranslationShift > successfulShiftThreshold) {
             mScrollInterpolator = scrollInterpolatorForVelocity(velocity);
             mOpenCloseAnimator.setDuration(BaseSwipeDetector.calculateDuration(
                     velocity, TRANSLATION_SHIFT_CLOSED - mTranslationShift));
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index 19c28b4..bfb75f0 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -62,7 +62,6 @@
 
     private final SurfaceView mSurfaceView;
 
-
     private View mIcon;
     private GestureNavContract mContract;
 
@@ -103,7 +102,13 @@
     private void removeViewFromParent() {
         mPicture.beginRecording(1, 1);
         mPicture.endRecording();
-        mLauncher.getDragLayer().removeView(this);
+        mLauncher.getDragLayer().removeViewInLayout(this);
+    }
+
+    private void removeViewImmediate() {
+        // Cancel any pending remove
+        Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(mRemoveViewRunnable);
+        removeViewFromParent();
     }
 
     /**
@@ -115,9 +120,7 @@
         view.mContract = contract;
         view.mIsOpen = true;
 
-        // Cancel any pending remove
-        Executors.MAIN_EXECUTOR.getHandler().removeCallbacks(view.mRemoveViewRunnable);
-        view.removeViewFromParent();
+        view.removeViewImmediate();
         launcher.getDragLayer().addView(view);
     }
 
@@ -129,6 +132,7 @@
     @Override
     public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
         close(false);
+        removeViewImmediate();
         return false;
     }
 
@@ -197,7 +201,7 @@
 
     private void sendIconInfo() {
         if (mContract != null && !mIconPosition.isEmpty()) {
-            mContract.sendEndPosition(mIconPosition, mSurfaceView.getSurfaceControl());
+            mContract.sendEndPosition(mIconPosition, mLauncher, mSurfaceView.getSurfaceControl());
         }
     }