Merge "Hide the Taskbar when user leaves PiP mode" into tm-dev
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index d76484c..a62e9d1 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -186,6 +186,7 @@
         } else {
             recentsCallback = callback;
         }
+        mRecentsView.cleanupRemoteTargets();
         mRecentsAnimationController.finish(
                 mAppCanEnterPip /* toRecents */, recentsCallback, true /* sendUserLeaveHint */);
     }
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index e9571e0..50d1244 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -239,6 +239,7 @@
 
     @Override
     protected void finishRecentsControllerToHome(Runnable callback) {
+        mRecentsView.cleanupRemoteTargets();
         mRecentsAnimationController.finish(
                 true /* toRecents */, callback, true /* sendUserLeaveHint */);
     }
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index f3ad0f6..ee69fc3 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -111,7 +111,7 @@
         if (mInitialTaskIntent != null) {
             fillInIntent = new Intent();
             if (TextUtils.equals(mInitialTaskIntent.getComponent().getPackageName(),
-                    task.topActivity.getPackageName())) {
+                    task.getTopComponent().getPackageName())) {
                 fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
             }
         } else {
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
index cfb0056..d869fed 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskThumbnailView.java
@@ -42,8 +42,6 @@
     private @Nullable BitmapShader mBitmapShader;
     private @Nullable Bitmap mBitmap;
 
-    private FloatingTaskView.FullscreenDrawParams mFullscreenParams;
-
     public FloatingTaskThumbnailView(Context context) {
         this(context, null);
     }
@@ -58,18 +56,18 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (mFullscreenParams == null || mBitmap == null) {
+        if (mBitmap == null) {
             return;
         }
 
         // Scale down the bitmap to fix x, and crop in y.
         float scale = 1.0f * getMeasuredWidth() / mBitmap.getWidth();
+        mMatrix.reset();
         mMatrix.postScale(scale, scale);
         mBitmapShader.setLocalMatrix(mMatrix);
 
-        canvas.drawRoundRect(0, 0, getMeasuredWidth(),  getMeasuredHeight(),
-                mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleX,
-                mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleY, mPaint);
+        FloatingTaskView parent = (FloatingTaskView) getParent();
+        parent.drawRoundedRect(canvas, mPaint);
     }
 
     public void setThumbnail(Bitmap bitmap) {
@@ -79,8 +77,4 @@
             mPaint.setShader(mBitmapShader);
         }
     }
-
-    public void setFullscreenParams(FloatingTaskView.FullscreenDrawParams fullscreenParams) {
-        mFullscreenParams = fullscreenParams;
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index c59dc18..fe5e1d0 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -3,11 +3,12 @@
 import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
 
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
@@ -31,15 +32,13 @@
 import com.android.quickstep.util.TaskCornerRadius;
 import com.android.systemui.shared.system.QuickStepContract;
 
-import java.util.function.Consumer;
-
 /**
  * Create an instance via
- * {@link #getFloatingTaskView(StatefulActivity, View, Bitmap, Drawable, RectF, Consumer)} to
+ * {@link #getFloatingTaskView(StatefulActivity, View, Bitmap, Drawable, RectF)} to
  * which will have the thumbnail from the provided existing TaskView overlaying the taskview itself.
  *
  * Can then animate the taskview using
- * {@link #addAnimation(PendingAnimation, RectF, Rect, View, boolean)}
+ * {@link #addAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}
  * giving a starting and ending bounds. Currently this is set to use the split placeholder view,
  * but it could be generified.
  *
@@ -47,13 +46,13 @@
  */
 public class FloatingTaskView extends FrameLayout {
 
+    private FloatingTaskThumbnailView mThumbnailView;
     private SplitPlaceholderView mSplitPlaceholderView;
     private RectF mStartingPosition;
     private final StatefulActivity mActivity;
     private final boolean mIsRtl;
-    private final FullscreenDrawParams mCurrentFullscreenParams;
+    private final FullscreenDrawParams mFullscreenParams;
     private PagedOrientationHandler mOrientationHandler;
-    private FloatingTaskThumbnailView mThumbnailView;
 
     public FloatingTaskView(Context context) {
         this(context, null);
@@ -67,17 +66,15 @@
         super(context, attrs, defStyleAttr);
         mActivity = BaseActivity.fromContext(context);
         mIsRtl = Utilities.isRtl(getResources());
-        mCurrentFullscreenParams = new FullscreenDrawParams(context);
+        mFullscreenParams = new FullscreenDrawParams(context);
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mThumbnailView = findViewById(R.id.thumbnail);
-        mThumbnailView.setFullscreenParams(mCurrentFullscreenParams);
         mSplitPlaceholderView = findViewById(R.id.split_placeholder);
         mSplitPlaceholderView.setAlpha(0);
-        mSplitPlaceholderView.setFullscreenParams(mCurrentFullscreenParams);
     }
 
     private void init(StatefulActivity launcher, View originalView, @Nullable Bitmap thumbnail,
@@ -94,20 +91,18 @@
         // Copy bounds of exiting thumbnail into ImageView
         mThumbnailView.setThumbnail(thumbnail);
 
+        mThumbnailView.setVisibility(VISIBLE);
+
         RecentsView recentsView = launcher.getOverviewPanel();
         mOrientationHandler = recentsView.getPagedOrientationHandler();
         mSplitPlaceholderView.setIcon(icon,
-                launcher.getDeviceProfile().overviewTaskIconDrawableSizePx);
+                mContext.getResources().getDimensionPixelSize(R.dimen.split_placeholder_icon_size));
         mSplitPlaceholderView.getIconView().setRotation(mOrientationHandler.getDegreesRotated());
     }
 
     /**
      * Configures and returns a an instance of {@link FloatingTaskView} initially matching the
      * appearance of {@code originalView}.
-     *
-     * @param additionalOffsetter optional, to set additional offsets to the FloatingTaskView
-     *                               to account for translations. If {@code null} then the
-     *                               translation values from originalView will be used
      */
     public static FloatingTaskView getFloatingTaskView(StatefulActivity launcher,
             View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut) {
@@ -133,21 +128,22 @@
         setLayoutParams(lp);
     }
 
-    public void update(RectF position, float progress) {
+    public void update(RectF bounds, float progress) {
         MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
 
-        float dX = position.left - mStartingPosition.left;
-        float dY = position.top - lp.topMargin;
-        float scaleX = position.width() / lp.width;
-        float scaleY = position.height() / lp.height;
+        float dX = bounds.left - mStartingPosition.left;
+        float dY = bounds.top - lp.topMargin;
+        float scaleX = bounds.width() / lp.width;
+        float scaleY = bounds.height() / lp.height;
 
-        mCurrentFullscreenParams.updateParams(position, progress, scaleX, scaleY);
+        mFullscreenParams.updateParams(bounds, progress, scaleX, scaleY);
 
         setTranslationX(dX);
         setTranslationY(dY);
         setScaleX(scaleX);
         setScaleY(scaleY);
         mSplitPlaceholderView.invalidate();
+        mThumbnailView.invalidate();
 
         float childScaleX = 1f / scaleX;
         float childScaleY = 1f / scaleY;
@@ -178,8 +174,8 @@
     }
 
     public void addAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds,
-            boolean fadeWithThumbnail, boolean isInitialSplit) {
-        mCurrentFullscreenParams.setIsInitialSplit(isInitialSplit);
+            boolean fadeWithThumbnail, boolean isStagedTask) {
+        mFullscreenParams.setIsStagedTask(isStagedTask);
         final BaseDragLayer dragLayer = mActivity.getDragLayer();
         int[] dragLayerBounds = new int[2];
         dragLayer.getLocationOnScreen(dragLayerBounds);
@@ -219,6 +215,25 @@
         transitionAnimator.addUpdateListener(listener);
     }
 
+    public void drawRoundedRect(Canvas canvas, Paint paint) {
+        if (mFullscreenParams == null) {
+            return;
+        }
+
+        canvas.drawRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(),
+                mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleX,
+                mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleY,
+                paint);
+    }
+
+    public float getFullscreenScaleX() {
+        return mFullscreenParams.mScaleX;
+    }
+
+    public float getFullscreenScaleY() {
+        return mFullscreenParams.mScaleY;
+    }
+
     private static class SplitOverlayProperties {
 
         private final float finalTaskViewScaleX;
@@ -247,9 +262,8 @@
 
         private final float mCornerRadius;
         private final float mWindowCornerRadius;
-
-        public boolean mIsInitialSplit = true;
-        public final RectF mFloatingTaskViewBounds = new RectF();
+        public boolean mIsStagedTask;
+        public final RectF mBounds = new RectF();
         public float mCurrentDrawnCornerRadius;
         public float mScaleX = 1;
         public float mScaleY = 1;
@@ -261,17 +275,16 @@
             mCurrentDrawnCornerRadius = mCornerRadius;
         }
 
-        public void updateParams(RectF floatingTaskViewBounds, float progress, float scaleX,
-                float scaleY) {
-            mFloatingTaskViewBounds.set(floatingTaskViewBounds);
+        public void updateParams(RectF bounds, float progress, float scaleX, float scaleY) {
+            mBounds.set(bounds);
             mScaleX = scaleX;
             mScaleY = scaleY;
-            mCurrentDrawnCornerRadius = mIsInitialSplit ? 0 :
+            mCurrentDrawnCornerRadius = mIsStagedTask ? mWindowCornerRadius :
                     Utilities.mapRange(progress, mCornerRadius, mWindowCornerRadius);
         }
 
-        public void setIsInitialSplit(boolean isInitialSplit) {
-            mIsInitialSplit = isInitialSplit;
+        public void setIsStagedTask(boolean isStagedTask) {
+            mIsStagedTask = isStagedTask;
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index da3b77b..22491bc 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -425,6 +425,7 @@
     private final int mScrollHapticMinGapMillis;
     private final RecentsModel mModel;
     private final int mSplitPlaceholderSize;
+    private final int mSplitPlaceholderInset;
     private final ClearAllButton mClearAllButton;
     private final Rect mClearAllButtonDeadZoneRect = new Rect();
     private final Rect mTaskViewDeadZoneRect = new Rect();
@@ -697,6 +698,8 @@
         setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
         mSplitPlaceholderSize = getResources().getDimensionPixelSize(
                 R.dimen.split_placeholder_size);
+        mSplitPlaceholderInset = getResources().getDimensionPixelSize(
+                R.dimen.split_placeholder_inset);
         mSquaredTouchSlop = squaredTouchSlop(context);
 
         mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
@@ -2702,7 +2705,7 @@
      */
     private void createInitialSplitSelectAnimation(PendingAnimation anim) {
         mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
-                mActivity.getDeviceProfile(),
+                mSplitPlaceholderInset, mActivity.getDeviceProfile(),
                 mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
 
         RectF startingTaskRect = new RectF();
@@ -2714,7 +2717,7 @@
                     mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
             mFirstFloatingTaskView.setAlpha(1);
             mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
-                    mTempRect, true /* fadeWithThumbnail */, true /* isInitialSplit */);
+                    mTempRect, true /* fadeWithThumbnail */, true /* isStagedTask */);
         } else {
             mSplitSelectSource.view.setVisibility(INVISIBLE);
             mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
@@ -2722,7 +2725,7 @@
                     mSplitSelectSource.drawable, startingTaskRect);
             mFirstFloatingTaskView.setAlpha(1);
             mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
-                    mTempRect, true /* fadeWithThumbnail */, true /* isInitialSplit */);
+                    mTempRect, true /* fadeWithThumbnail */, true /* isStagedTask */);
         }
         anim.addEndListener(success -> {
             if (success) {
@@ -4002,14 +4005,14 @@
         mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
         mFirstFloatingTaskView.addAnimation(pendingAnimation,
                 new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
-                false /* fadeWithThumbnail */, false /* isInitialSplit */);
+                false /* fadeWithThumbnail */, true /* isStagedTask */);
 
         mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                 thumbnailView, thumbnailView.getThumbnail(),
                 iconView.getDrawable(), secondTaskStartingBounds);
         mSecondFloatingTaskView.setAlpha(1);
         mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
-                secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isInitialSplit */);
+                secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
         pendingAnimation.addEndListener(aBoolean ->
                 mSplitSelectStateController.setSecondTask(
                         task, aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));
@@ -4077,10 +4080,9 @@
 
     protected void onRotateInSplitSelectionState() {
         mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
-                mActivity.getDeviceProfile(),
+                mSplitPlaceholderInset, mActivity.getDeviceProfile(),
                 mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
         mTempRectF.set(mTempRect);
-        // TODO(194414938) set correct corner radius
         mFirstFloatingTaskView.updateOrientationHandler(mOrientationHandler);
         mFirstFloatingTaskView.update(mTempRectF, /*progress=*/1f);
 
@@ -4281,7 +4283,7 @@
         }
         mPendingAnimation.addEndListener(isSuccess -> {
             if (isSuccess) {
-                if (tv.getTaskIds()[1] != -1) {
+                if (tv.getTaskIds()[1] != -1 && mRemoteTargetHandles != null) {
                     // TODO(b/194414938): make this part of the animations instead.
                     TaskViewUtils.createSplitAuxiliarySurfacesAnimator(
                             mRemoteTargetHandles[0].getTransformParams().getTargetSet().nonApps,
diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
index d37dfbf..7444217 100644
--- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
@@ -19,11 +19,11 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.TypedValue;
-import android.view.Gravity;
 import android.widget.FrameLayout;
 
 import androidx.annotation.Nullable;
@@ -31,8 +31,7 @@
 public class SplitPlaceholderView extends FrameLayout {
 
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-
-    private FloatingTaskView.FullscreenDrawParams mFullscreenParams;
+    private final Rect mTempRect = new Rect();
 
     public static final FloatProperty<SplitPlaceholderView> ALPHA_FLOAT =
             new FloatProperty<SplitPlaceholderView>("SplitViewAlpha") {
@@ -54,7 +53,7 @@
     public SplitPlaceholderView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mPaint.setColor(getThemePrimaryColor(context));
+        mPaint.setColor(getThemeBackgroundColor(context));
         setWillNotDraw(false);
     }
 
@@ -64,6 +63,19 @@
         drawBackground(canvas);
 
         super.dispatchDraw(canvas);
+
+        if (mIconView != null) {
+            // Center the icon view in the visible area.
+            getLocalVisibleRect(mTempRect);
+            FloatingTaskView parent = (FloatingTaskView) getParent();
+            FrameLayout.LayoutParams params =
+                    (FrameLayout.LayoutParams) mIconView.getLayoutParams();
+            params.leftMargin = Math.round(mTempRect.centerX() / parent.getFullscreenScaleX()
+                    - 1.0f * mIconView.getDrawableWidth() / 2);
+            params.topMargin = Math.round(mTempRect.centerY() / parent.getFullscreenScaleY()
+                    - 1.0f * mIconView.getDrawableHeight() / 2);
+            mIconView.setLayoutParams(params);
+        }
     }
 
     @Nullable
@@ -71,10 +83,6 @@
         return mIconView;
     }
 
-    public void setFullscreenParams(FloatingTaskView.FullscreenDrawParams fullscreenParams) {
-        mFullscreenParams = fullscreenParams;
-    }
-
     public void setIcon(Drawable drawable, int iconSize) {
         if (mIconView == null) {
             mIconView = new IconView(getContext());
@@ -83,23 +91,17 @@
         mIconView.setDrawable(drawable);
         mIconView.setDrawableSize(iconSize, iconSize);
         FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(iconSize, iconSize);
-        params.gravity = Gravity.CENTER;
         mIconView.setLayoutParams(params);
     }
 
     private void drawBackground(Canvas canvas) {
-        if (mFullscreenParams == null) {
-            return;
-        }
-
-        canvas.drawRoundRect(0, 0, getMeasuredWidth(),  getMeasuredHeight(),
-                mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleX,
-                mFullscreenParams.mCurrentDrawnCornerRadius / mFullscreenParams.mScaleY, mPaint);
+        FloatingTaskView parent = (FloatingTaskView) getParent();
+        parent.drawRoundedRect(canvas, mPaint);
     }
 
-    private static int getThemePrimaryColor(Context context) {
+    private static int getThemeBackgroundColor(Context context) {
         final TypedValue value = new TypedValue();
-        context.getTheme().resolveAttribute(android.R.attr.colorPrimary, value, true);
+        context.getTheme().resolveAttribute(android.R.attr.colorBackground, value, true);
         return value.data;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 11f9ddd..60b0d17 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -50,7 +50,6 @@
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.icons.BitmapRenderer;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SystemUiController;
 import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
@@ -162,23 +161,6 @@
         setThumbnail(task, thumbnailData, true /* refreshNow */);
     }
 
-    /**
-     * By combining the two in a single bitmap then we only have to do a single draw
-     * call in the onDraw function. Also, this fixes a bug where the background was
-     * visible in the corners because of anti-aliasing.
-     */
-    public Bitmap combineThumbnailAndBackground(Bitmap bm) {
-        return BitmapRenderer.createHardwareBitmap(bm.getWidth(), bm.getHeight(), c -> {
-            final boolean drawBackgroundOnly = mTask == null || mTask.isLocked;
-            if (drawBackgroundOnly) {
-                c.drawPaint(mBackgroundPaint);
-            } else {
-                c.drawPaint(mBackgroundPaint);
-                c.drawBitmap(bm, 0, 0, null);
-            }
-        });
-    }
-
     /** Updates the shader, paint, matrix to redraw. */
     public void refresh() {
         refresh(false);
@@ -191,7 +173,6 @@
     private void refresh(boolean shouldRefreshOverlay) {
         if (mThumbnailData != null && mThumbnailData.thumbnail != null) {
             Bitmap bm = mThumbnailData.thumbnail;
-            bm = combineThumbnailAndBackground(bm);
             bm.prepareToDraw();
             mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
             mPaint.setShader(mBitmapShader);
@@ -213,6 +194,7 @@
      * <p>
      * If dimAlpha is 0, no dimming is applied; if dimAlpha is 1, the thumbnail will be the
      * extracted background color.
+     *
      */
     public void setDimAlpha(float dimAlpha) {
         mDimAlpha = dimAlpha;
@@ -314,6 +296,18 @@
                 return;
             }
         }
+
+        // Always draw the background since the snapshots might be translucent or partially empty
+        // (For example, tasks been reparented out of dismissing split root when drag-to-dismiss
+        // split screen).
+        canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint);
+
+        final boolean drawBackgroundOnly = mTask == null || mTask.isLocked || mBitmapShader == null
+                || mThumbnailData == null;
+        if (drawBackgroundOnly) {
+            return;
+        }
+
         canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
     }
 
@@ -344,6 +338,7 @@
 
     private void updateThumbnailPaintFilter() {
         ColorFilter filter = getColorFilter(mDimAlpha);
+        mBackgroundPaint.setColorFilter(filter);
         int alpha = (int) (mDimAlpha * 255);
         mDimmingPaintAfterClearing.setAlpha(alpha);
         if (mBitmapShader != null) {
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a6abee2..0615053 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -359,7 +359,9 @@
     <dimen name="overview_grid_side_margin">0dp</dimen>
     <dimen name="overview_grid_row_spacing">0dp</dimen>
     <dimen name="overview_page_spacing">0dp</dimen>
-    <dimen name="split_placeholder_size">110dp</dimen>
+    <dimen name="split_placeholder_size">72dp</dimen>
+    <dimen name="split_placeholder_inset">16dp</dimen>
+    <dimen name="split_placeholder_icon_size">44dp</dimen>
     <dimen name="task_menu_width_grid">200dp</dimen>
 
 
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index be2cd88..baee49f 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -16,6 +16,7 @@
 package com.android.launcher3;
 
 import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
 import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
@@ -91,6 +92,14 @@
                 }
             };
 
+    protected static final PageTranslationProvider DEFAULT_PAGE_TRANSLATION_PROVIDER =
+            new PageTranslationProvider(DEACCEL_2) {
+                @Override
+                public float getPageTranslation(int pageIndex) {
+                    return 0;
+                }
+            };
+
     private static final LauncherState[] sAllStates = new LauncherState[10];
 
     /**
@@ -288,6 +297,25 @@
         };
     }
 
+    /**
+     * Gets the translation provider for workspace pages.
+     */
+    public PageTranslationProvider getWorkspacePageTranslationProvider(Launcher launcher) {
+        if (this != SPRING_LOADED || !launcher.getDeviceProfile().isTwoPanels) {
+            return DEFAULT_PAGE_TRANSLATION_PROVIDER;
+        }
+        final float quarterPageSpacing = launcher.getWorkspace().getPageSpacing() / 4f;
+        return new PageTranslationProvider(DEACCEL_2) {
+            @Override
+            public float getPageTranslation(int pageIndex) {
+                boolean isRtl = launcher.getWorkspace().mIsRtl;
+                boolean isFirstPage = pageIndex % 2 == 0;
+                return ((isFirstPage && !isRtl) || (!isFirstPage && isRtl)) ? -quarterPageSpacing
+                        : quarterPageSpacing;
+            }
+        };
+    }
+
     @Override
     public LauncherState getHistoryForState(LauncherState previousState) {
         // No history is supported
@@ -318,6 +346,23 @@
         public abstract float getPageAlpha(int pageIndex);
     }
 
+    /**
+     * Provider for the translation and animation interpolation of workspace pages.
+     */
+    public abstract static class PageTranslationProvider {
+
+        public final Interpolator interpolator;
+
+        public PageTranslationProvider(Interpolator interpolator) {
+            this.interpolator = interpolator;
+        }
+
+        /**
+         * Gets the translation of the workspace page at the provided page index.
+         */
+        public abstract float getPageTranslation(int pageIndex);
+    }
+
     public static class ScaleAndTranslation {
         public float scale;
         public float translationX;
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index d94e84c..1e09b2d 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -39,6 +39,7 @@
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_PAGE_TRANSLATE_X;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
@@ -49,6 +50,7 @@
 import android.view.animation.Interpolator;
 
 import com.android.launcher3.LauncherState.PageAlphaProvider;
+import com.android.launcher3.LauncherState.PageTranslationProvider;
 import com.android.launcher3.LauncherState.ScaleAndTranslation;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
@@ -155,6 +157,12 @@
                 scaleAndTranslation.translationX, translationInterpolator);
         propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_Y,
                 scaleAndTranslation.translationY, translationInterpolator);
+        PageTranslationProvider pageTranslationProvider = state.getWorkspacePageTranslationProvider(
+                mLauncher);
+        for (int i = 0; i < childCount; i++) {
+            applyPageTranslation((CellLayout) mWorkspace.getChildAt(i), i, pageTranslationProvider,
+                    propertySetter, config);
+        }
 
         Interpolator hotseatTranslationInterpolator = config.getInterpolator(
                 ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
@@ -202,6 +210,16 @@
                 pageAlpha, fadeInterpolator);
     }
 
+    private void applyPageTranslation(CellLayout cellLayout, int childIndex,
+            PageTranslationProvider pageTranslationProvider, PropertySetter propertySetter,
+            StateAnimationConfig config) {
+        float pageTranslation = pageTranslationProvider.getPageTranslation(childIndex);
+        Interpolator translationInterpolator = config.getInterpolator(
+                ANIM_WORKSPACE_PAGE_TRANSLATE_X, pageTranslationProvider.interpolator);
+        propertySetter.setFloat(cellLayout, VIEW_TRANSLATE_X, pageTranslation,
+                translationInterpolator);
+    }
+
     /**
      * Returns a spring based animator for the scale property of {@param workspace}.
      */
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 8ba2070..7727fae 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -259,7 +259,7 @@
             "Enable the new grid migration logic, keeping pages when src < dest");
 
     public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
-            "ENABLE_ONE_SEARCH_MOTION", false, "Enables animations in OneSearch.");
+            "ENABLE_ONE_SEARCH_MOTION", true, "Enables animations in OneSearch.");
 
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index bd6f7d3..f04e685 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -62,6 +62,7 @@
             ANIM_OVERVIEW_MODAL,
             ANIM_DEPTH,
             ANIM_OVERVIEW_ACTIONS_FADE,
+            ANIM_WORKSPACE_PAGE_TRANSLATE_X,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AnimType {}
@@ -80,8 +81,9 @@
     public static final int ANIM_OVERVIEW_MODAL = 12;
     public static final int ANIM_DEPTH = 13;
     public static final int ANIM_OVERVIEW_ACTIONS_FADE = 14;
+    public static final int ANIM_WORKSPACE_PAGE_TRANSLATE_X = 15;
 
-    private static final int ANIM_TYPES_COUNT = 15;
+    private static final int ANIM_TYPES_COUNT = 16;
 
     protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
 
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 217a558..4fcba18 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -394,12 +394,21 @@
     }
 
     @Override
-    public void getInitialSplitPlaceholderBounds(int placeholderHeight, DeviceProfile dp,
-            @StagePosition int stagePosition, Rect out) {
+    public void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
+            DeviceProfile dp, @StagePosition int stagePosition, Rect out) {
         // In fake land/seascape, the placeholder always needs to go to the "top" of the device,
         // which is the same bounds as 0 rotation.
         int width = dp.widthPx;
         out.set(0, 0, width, placeholderHeight);
+        out.inset(placeholderInset, 0);
+
+        // Adjust the top to account for content off screen. This will help to animate the view in
+        // with rounded corners.
+        int screenWidth = dp.widthPx;
+        int screenHeight = dp.heightPx;
+        int totalHeight = (int) (1.0f * screenHeight / 2 * (screenWidth - 2 * placeholderInset)
+                / screenWidth);
+        out.top -= (totalHeight - placeholderHeight);
     }
 
     @Override
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 1b17126..850eaaf 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -110,10 +110,10 @@
     int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect);
     List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp);
     /**
-     * @param splitholderSize height of placeholder view in portrait, width in landscape
+     * @param placeholderHeight height of placeholder view in portrait, width in landscape
      */
-    void getInitialSplitPlaceholderBounds(int splitholderSize, DeviceProfile dp,
-            @StagePosition int stagePosition, Rect out);
+    void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
+            DeviceProfile dp, @StagePosition int stagePosition, Rect out);
 
     /**
      * @param splitDividerSize height of split screen drag handle in portrait, width in landscape
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 7e1cb25..d132901 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -436,29 +436,48 @@
     }
 
     @Override
-    public void getInitialSplitPlaceholderBounds(int placeholderHeight, DeviceProfile dp,
-            @StagePosition int stagePosition, Rect out) {
-        int width = dp.widthPx;
-        out.set(0, 0, width, placeholderHeight);
+    public void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
+            DeviceProfile dp, @StagePosition int stagePosition, Rect out) {
+        int screenWidth = dp.widthPx;
+        int screenHeight = dp.heightPx;
+        out.set(0, 0, screenWidth, placeholderHeight);
         if (!dp.isLandscape) {
             // portrait, phone or tablet - spans width of screen, nothing else to do
+            out.inset(placeholderInset, 0);
+
+            // Adjust the top to account for content off screen. This will help to animate the view
+            // in with rounded corners.
+            int totalHeight = (int) (1.0f * screenHeight / 2 * (screenWidth - 2 * placeholderInset)
+                    / screenWidth);
+            out.top -= (totalHeight - placeholderHeight);
             return;
         }
 
         // Now we rotate the portrait rect depending on what side we want pinned
         boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
 
-        int screenHeight = dp.heightPx;
-        float postRotateScale = (float) screenHeight / width;
+        float postRotateScale = (float) screenHeight / screenWidth;
         mTmpMatrix.reset();
         mTmpMatrix.postRotate(pinToRight ? 90 : 270);
-        mTmpMatrix.postTranslate(pinToRight ? width : 0, pinToRight ? 0 : width);
+        mTmpMatrix.postTranslate(pinToRight ? screenWidth : 0, pinToRight ? 0 : screenWidth);
         // The placeholder height stays constant after rotation, so we don't change width scale
         mTmpMatrix.postScale(1, postRotateScale);
 
         mTmpRectF.set(out);
         mTmpMatrix.mapRect(mTmpRectF);
+        mTmpRectF.inset(0, placeholderInset);
         mTmpRectF.roundOut(out);
+
+        // Adjust the top to account for content off screen. This will help to animate the view in
+        // with rounded corners.
+        int totalWidth = (int) (1.0f * screenWidth / 2 * (screenHeight - 2 * placeholderInset)
+                / screenHeight);
+        int width = out.width();
+        if (pinToRight) {
+            out.right += totalWidth - width;
+        } else {
+            out.left -= totalWidth - width;
+        }
     }
 
     @Override