Merge "Adding a sliding tab strip to the custom tab layout." into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 26f5d5b..1176034 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -29,9 +29,6 @@
  */
 public class OverviewState extends LauncherState {
 
-    // The percent to shrink the workspace during overview mode
-    public static final float SCALE_FACTOR = 0.7f;
-
     private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_MULTI_PAGE;
 
     public OverviewState(int id) {
diff --git a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
index 1a8ae2a..34e3c4e 100644
--- a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
+++ b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
@@ -23,7 +23,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.os.Build;
-import android.os.UserHandle;
 import android.support.annotation.BinderThread;
 import android.support.annotation.UiThread;
 import android.util.FloatProperty;
@@ -32,6 +31,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
@@ -40,11 +40,7 @@
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.states.InternalStateHandler;
-import com.android.launcher3.uioverrides.OverviewState;
 import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
-import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.BackgroundExecutor;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 
 import java.util.concurrent.ExecutionException;
@@ -119,25 +115,10 @@
     }
 
     @Override
-    public void onCreate(Launcher launcher) {
-        mLauncher = launcher;
-        mDragView = new SnapshotDragView(mLauncher, mTaskSnapshot);
-        mLauncher.getDragLayer().addView(mDragView);
-        mDragView.setPivotX(0);
-        mDragView.setPivotY(0);
-        mRecentsView = mLauncher.getOverviewPanel();
-        mHotseat = mLauncher.getHotseat();
+    protected void init(Launcher launcher, boolean alreadyOnHome) {
+        AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
+        launcher.getStateManager().goToState(LauncherState.OVERVIEW, alreadyOnHome);
 
-        // Optimization
-        mLauncher.getAppsView().setVisibility(View.GONE);
-
-        // Launch overview
-        mRecentsView.update(consumeLastLoadPlan());
-        mLauncher.getStateManager().goToState(LauncherState.OVERVIEW, false /* animate */);
-    }
-
-    @Override
-    public void onNewIntent(Launcher launcher, boolean alreadyOnHome) {
         mLauncher = launcher;
         mDragView = new SnapshotDragView(mLauncher, mTaskSnapshot);
         mLauncher.getDragLayer().addView(mDragView);
@@ -151,7 +132,6 @@
 
         // Launch overview, animate if already on home
         mRecentsView.update(consumeLastLoadPlan());
-        mLauncher.getStateManager().goToState(LauncherState.OVERVIEW, alreadyOnHome);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/TaskThumbnailView.java
index 55d22e0..6e8bbeb 100644
--- a/quickstep/src/com/android/quickstep/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/TaskThumbnailView.java
@@ -50,7 +50,7 @@
     protected Paint mBgFillPaint = new Paint();
     protected BitmapShader mBitmapShader;
 
-    private float mDimAlpha;
+    private float mDimAlpha = 1f;
     private LightingColorFilter mLightingColorFilter = new LightingColorFilter(Color.WHITE, 0);
 
     public TaskThumbnailView(Context context) {
@@ -64,7 +64,6 @@
     public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         setWillNotDraw(false);
-        setDimAlpha(1f);
         setClipToOutline(true);
     }
 
diff --git a/quickstep/src/com/android/quickstep/TaskView.java b/quickstep/src/com/android/quickstep/TaskView.java
index f6408a8..029afd6 100644
--- a/quickstep/src/com/android/quickstep/TaskView.java
+++ b/quickstep/src/com/android/quickstep/TaskView.java
@@ -55,7 +55,6 @@
 
     public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        setWillNotDraw(false);
         setOnClickListener((view) -> {
             launchTask(true /* animate */);
         });
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 1218176..1ff29cf 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -17,8 +17,6 @@
 
 import static android.view.MotionEvent.INVALID_POINTER_ID;
 
-import static com.android.launcher3.states.InternalStateHandler.EXTRA_STATE_HANDLER;
-
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityOptions;
 import android.app.Service;
@@ -31,7 +29,6 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -42,12 +39,10 @@
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.Options;
 import com.android.systemui.shared.recents.model.RecentsTaskLoader;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.BackgroundExecutor;
@@ -81,7 +76,8 @@
     private Intent mHomeIntent;
     private ComponentName mLauncher;
 
-
+    private int mDisplayRotation;
+    private final Point mDisplaySize = new Point();
     private final PointF mDownPos = new PointF();
     private final PointF mLastPos = new PointF();
     private int mActivePointerId = INVALID_POINTER_ID;
@@ -133,6 +129,9 @@
                 mDownPos.set(ev.getX(), ev.getY());
                 mLastPos.set(mDownPos);
                 mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
+                Display display = getSystemService(WindowManager.class).getDefaultDisplay();
+                display.getRealSize(mDisplaySize);
+                mDisplayRotation = display.getRotation();
 
                 mRunningTask = mAM.getRunningTask();
                 if (mRunningTask == null || mRunningTask.topActivity.equals(mLauncher)) {
@@ -202,37 +201,20 @@
 
         // Preload and start the recents activity on a background thread
         final Context context = this;
-        final int runningTaskId = ActivityManagerWrapper.getInstance().getRunningTask().id;
         final RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(context);
         Future<RecentsTaskLoadPlan> loadPlanFuture = BackgroundExecutor.get().submit(() -> {
             // Preload the plan
             RecentsTaskLoader loader = TouchInteractionService.getRecentsTaskLoader();
-            loadPlan.preloadPlan(loader, runningTaskId, UserHandle.myUserId());
+            loadPlan.preloadPlan(loader, mRunningTask.id, UserHandle.myUserId());
 
-            // Pass the
-            Bundle extras = new Bundle();
-            extras.putBinder(EXTRA_STATE_HANDLER, mInteractionHandler);
-
-            // Start the activity
-            Intent homeIntent = new Intent(mHomeIntent);
-            homeIntent.putExtras(extras);
+            // Start the activity with our custom handler
+            Intent homeIntent = mInteractionHandler.addToIntent(new Intent(mHomeIntent));
             startActivity(homeIntent, ActivityOptions.makeCustomAnimation(this, 0, 0).toBundle());
             /*
             ActivityManagerWrapper.getInstance().startRecentsActivity(null, options,
                     ActivityOptions.makeCustomAnimation(this, 0, 0), UserHandle.myUserId(),
                     null, null);
              */
-
-            // Kick off loading of the plan while the activity is starting
-            Options loadOpts = new Options();
-            loadOpts.runningTaskId = runningTaskId;
-            loadOpts.loadIcons = true;
-            loadOpts.loadThumbnails = true;
-            loadOpts.numVisibleTasks = 2;
-            loadOpts.numVisibleTaskThumbnails = 2;
-            loadOpts.onlyLoadForCache = false;
-            loadOpts.onlyLoadPausedActivities = false;
-            loader.loadTasks(loadPlan, loadOpts);
         }, loadPlan);
 
         mInteractionHandler.setLastLoadPlan(loadPlanFuture);
@@ -243,7 +225,7 @@
             mVelocityTracker.computeCurrentVelocity(1000,
                     ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
 
-            mInteractionHandler.endTouch(mVelocityTracker.getXVelocity(mActivePointerId));
+            mInteractionHandler.endTouch(mVelocityTracker.getYVelocity(mActivePointerId));
             mInteractionHandler = null;
         }
         mVelocityTracker.recycle();
@@ -255,14 +237,11 @@
             Log.e(TAG, "Never received systemUIProxy");
             return null;
         }
-        Display display = getSystemService(WindowManager.class).getDefaultDisplay();
-        Point size = new Point();
-        display.getRealSize(size);
 
         // TODO: We are using some hardcoded layers for now, to best approximate the activity layers
         try {
-            return mISystemUiProxy.screenshot(new Rect(), size.x, size.y, 0, 100000, false,
-                    display.getRotation());
+            return mISystemUiProxy.screenshot(new Rect(), mDisplaySize.x, mDisplaySize.y, 0, 100000,
+                    false, mDisplayRotation);
         } catch (RemoteException e) {
             Log.e(TAG, "Error capturing snapshot", e);
             return null;
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index d8c4efa..cfb55cc 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -53,6 +53,7 @@
 public abstract class ButtonDropTarget extends TextView
         implements DropTarget, DragController.DragListener, OnClickListener {
 
+    private static final int[] sTempCords = new int[2];
     private static final int DRAG_VIEW_DROP_DURATION = 285;
 
     private final boolean mHideParentOnDisable;
@@ -257,9 +258,9 @@
         super.getHitRect(outRect);
         outRect.bottom += mBottomDragPadding;
 
-        int[] coords = new int[2];
-        mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, coords);
-        outRect.offsetTo(coords[0], coords[1]);
+        sTempCords[0] = sTempCords[1] = 0;
+        mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, sTempCords);
+        outRect.offsetTo(sTempCords[0], sTempCords[1]);
     }
 
     public Rect getIconRect(DragObject dragObject) {
diff --git a/src/com/android/launcher3/InsettableFrameLayout.java b/src/com/android/launcher3/InsettableFrameLayout.java
index be76490..60f5ca2 100644
--- a/src/com/android/launcher3/InsettableFrameLayout.java
+++ b/src/com/android/launcher3/InsettableFrameLayout.java
@@ -9,8 +9,7 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
-public class InsettableFrameLayout extends FrameLayout implements
-    ViewGroup.OnHierarchyChangeListener, Insettable {
+public class InsettableFrameLayout extends FrameLayout implements Insettable {
 
     @ViewDebug.ExportedProperty(category = "launcher")
     protected Rect mInsets = new Rect();
@@ -21,7 +20,6 @@
 
     public InsettableFrameLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
-        setOnHierarchyChangeListener(this);
     }
 
     public void setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets) {
@@ -95,12 +93,8 @@
     }
 
     @Override
-    public void onChildViewAdded(View parent, View child) {
+    public void onViewAdded(View child) {
+        super.onViewAdded(child);
         setFrameLayoutChildInsets(child, mInsets, new Rect());
     }
-
-    @Override
-    public void onChildViewRemoved(View parent, View child) {
-    }
-
 }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 60c00fb..782ddc3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -107,7 +107,6 @@
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
-import com.android.launcher3.dragndrop.PinItemDragListener;
 import com.android.launcher3.dynamicui.WallpaperColorInfo;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
@@ -359,9 +358,27 @@
 
         mPopupDataProvider = new PopupDataProvider(this);
 
-        restoreState(savedInstanceState);
+        mRotationEnabled = getResources().getBoolean(R.bool.allow_rotation);
+        // In case we are on a device with locked rotation, we should look at preferences to check
+        // if the user has specifically allowed rotation.
+        if (!mRotationEnabled) {
+            mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext());
+            mRotationPrefChangeHandler = new RotationPrefChangeHandler();
+            mSharedPrefs.registerOnSharedPreferenceChangeListener(mRotationPrefChangeHandler);
+        }
 
-        InternalStateHandler.handleCreate(this, getIntent());
+        boolean internalStateHandled = InternalStateHandler.handleCreate(this, getIntent());
+        if (internalStateHandled) {
+            // Temporarily enable the rotation
+            mRotationEnabled = true;
+
+            if (savedInstanceState != null) {
+                // InternalStateHandler has already set the appropriate state.
+                // We dont need to do anything.
+                savedInstanceState.remove(RUNTIME_STATE);
+            }
+        }
+        restoreState(savedInstanceState);
 
         // We only load the page synchronously if the user rotates (or triggers a
         // configuration change) while launcher is in the foreground
@@ -369,10 +386,13 @@
         if (savedInstanceState != null) {
             currentScreen = savedInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN, currentScreen);
         }
+
         if (!mModel.startLoader(currentScreen)) {
-            // If we are not binding synchronously, show a fade in animation when
-            // the first page bind completes.
-            mDragLayer.setAlpha(0);
+            if (!internalStateHandled) {
+                // If we are not binding synchronously, show a fade in animation when
+                // the first page bind completes.
+                mDragLayer.setAlpha(0);
+            }
         } else {
             // Pages bound synchronously.
             mWorkspace.setCurrentPage(currentScreen);
@@ -384,20 +404,6 @@
         mDefaultKeySsb = new SpannableStringBuilder();
         Selection.setSelection(mDefaultKeySsb, 0);
 
-        mRotationEnabled = getResources().getBoolean(R.bool.allow_rotation);
-        // In case we are on a device with locked rotation, we should look at preferences to check
-        // if the user has specifically allowed rotation.
-        if (!mRotationEnabled) {
-            mRotationEnabled = Utilities.isAllowRotationPrefEnabled(getApplicationContext());
-            mRotationPrefChangeHandler = new RotationPrefChangeHandler();
-            mSharedPrefs.registerOnSharedPreferenceChangeListener(mRotationPrefChangeHandler);
-        }
-
-        if (PinItemDragListener.handleDragRequest(this, getIntent())) {
-            // Temporarily enable the rotation
-            mRotationEnabled = true;
-        }
-
         // On large interfaces, or on devices that a user has specifically enabled screen rotation,
         // we want the screen to auto-rotate based on the current orientation
         setRequestedOrientation(mRotationEnabled
@@ -767,10 +773,7 @@
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onStop();
         }
-
-        if (Utilities.ATLEAST_NOUGAT_MR1) {
-            mAppWidgetHost.stopListening();
-        }
+        mAppWidgetHost.setListenIfResumed(false);
 
         if (!mAppLaunchSuccess) {
             getUserEventDispatcher().logActionCommand(Action.Command.STOP,
@@ -787,10 +790,7 @@
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onStart();
         }
-
-        if (Utilities.ATLEAST_NOUGAT_MR1) {
-            mAppWidgetHost.startListening();
-        }
+        mAppWidgetHost.setListenIfResumed(true);
 
         if (!isWorkspaceLoading()) {
             NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
@@ -1065,7 +1065,6 @@
 
         // Setup the drag controller (drop targets have to be added in reverse order in priority)
         mDragController.setMoveTarget(mWorkspace);
-        mDragController.addDropTarget(mWorkspace);
         mDropTargetBar.setup(mDragController);
 
         mAllAppsController.setupViews(mAppsView, mHotseat, mWorkspace);
@@ -1349,65 +1348,47 @@
         boolean shouldMoveToDefaultScreen = alreadyOnHome && isInState(NORMAL)
                 && AbstractFloatingView.getTopOpenView(this) == null;
         boolean isActionMain = Intent.ACTION_MAIN.equals(intent.getAction());
+        boolean internalStateHandled = InternalStateHandler
+                .handleNewIntent(this, intent, alreadyOnHome);
+
         if (isActionMain) {
-            if (mWorkspace == null) {
-                // Can be cases where mWorkspace is null, this prevents a NPE
-                return;
-            }
+            if (!internalStateHandled) {
+                // Note: There should be at most one log per method call. This is enforced
+                // implicitly by using if-else statements.
+                UserEventDispatcher ued = getUserEventDispatcher();
+                AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(this);
+                if (topOpenView != null) {
+                    topOpenView.logActionCommand(Action.Command.HOME_INTENT);
+                } else if (alreadyOnHome) {
+                    Target target = newContainerTarget(mStateManager.getState().containerType);
+                    target.pageIndex = mWorkspace.getCurrentPage();
+                    ued.logActionCommand(Action.Command.HOME_INTENT, target);
+                }
 
-            // Note: There should be at most one log per method call. This is enforced implicitly
-            // by using if-else statements.
-            UserEventDispatcher ued = getUserEventDispatcher();
-            AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(this);
-            if (topOpenView != null) {
-                topOpenView.logActionCommand(Action.Command.HOME_INTENT);
-            } else if (alreadyOnHome) {
-                Target target = newContainerTarget(mStateManager.getState().containerType);
-                target.pageIndex = mWorkspace.getCurrentPage();
-                ued.logActionCommand(Action.Command.HOME_INTENT, target);
-            }
+                // In all these cases, only animate if we're already on home
+                AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
 
-            // In all these cases, only animate if we're already on home
-            AbstractFloatingView.closeAllOpenViews(this, alreadyOnHome);
-            mStateManager.goToState(NORMAL, alreadyOnHome /* animated */);
+                mStateManager.goToState(NORMAL, alreadyOnHome /* animated */);
+
+                // Reset the apps view
+                if (!alreadyOnHome && mAppsView != null) {
+                    mAppsView.reset();
+                }
+
+                if (shouldMoveToDefaultScreen && !mWorkspace.isTouchActive()) {
+                    mWorkspace.post(mWorkspace::moveToDefaultScreen);
+                }
+            }
 
             final View v = getWindow().peekDecorView();
             if (v != null && v.getWindowToken() != null) {
                 UiThreadHelper.hideKeyboardAsync(this, v.getWindowToken());
             }
 
-            // Reset the apps view
-            if (!alreadyOnHome && mAppsView != null) {
-                mAppsView.reset();
-            }
-
             if (mLauncherCallbacks != null) {
                 mLauncherCallbacks.onHomeIntent();
             }
         }
-        PinItemDragListener.handleDragRequest(this, intent);
-
-        if (mLauncherCallbacks != null) {
-            mLauncherCallbacks.onNewIntent(intent);
-        }
-
-        // Defer moving to the default screen until after we callback to the LauncherCallbacks
-        // as slow logic in the callbacks eat into the time the scroller expects for the snapToPage
-        // animation.
-        if (isActionMain) {
-            if (shouldMoveToDefaultScreen && !mWorkspace.isTouchActive()) {
-
-                mWorkspace.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        if (mWorkspace != null) {
-                            mWorkspace.moveToDefaultScreen();
-                        }
-                    }
-                });
-            }
-        }
-        InternalStateHandler.handleNewIntent(this, intent, alreadyOnHome);
 
         TraceHelper.endSection("NEW_INTENT");
     }
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index 70440fa..9aa74b3 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -16,7 +16,8 @@
 
 package com.android.launcher3;
 
-import android.app.Activity;
+import static android.app.Activity.RESULT_CANCELED;
+
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
@@ -41,12 +42,17 @@
  */
 public class LauncherAppWidgetHost extends AppWidgetHost {
 
+    private static final int FLAG_LISTENING = 1;
+    private static final int FLAG_RESUMED = 1 << 1;
+    private static final int FLAG_LISTEN_IF_RESUMED = 1 << 2;
+
     public static final int APPWIDGET_HOST_ID = 1024;
 
     private final ArrayList<ProviderChangedListener> mProviderChangeListeners = new ArrayList<>();
     private final SparseArray<LauncherAppWidgetHostView> mViews = new SparseArray<>();
 
     private final Context mContext;
+    private int mFlags = FLAG_RESUMED;
 
     public LauncherAppWidgetHost(Context context) {
         super(context, APPWIDGET_HOST_ID);
@@ -66,7 +72,7 @@
         if (FeatureFlags.GO_DISABLE_WIDGETS) {
             return;
         }
-
+        mFlags |= FLAG_LISTENING;
         try {
             super.startListening();
         } catch (Exception e) {
@@ -85,10 +91,59 @@
         if (FeatureFlags.GO_DISABLE_WIDGETS) {
             return;
         }
-
+        mFlags &= ~FLAG_LISTENING;
         super.stopListening();
     }
 
+    /**
+     * Updates the resumed state of the host.
+     * When a host is not resumed, it defers calls to startListening until host is resumed again.
+     * But if the host was already listening, it will not call stopListening.
+     *
+     * @see #setListenIfResumed(boolean)
+     */
+    public void setResumed(boolean isResumed) {
+        if (isResumed == ((mFlags & FLAG_RESUMED) != 0)) {
+            return;
+        }
+        if (isResumed) {
+            mFlags |= FLAG_RESUMED;
+            // Start listening if we were supposed to start listening on resume
+            if ((mFlags & FLAG_LISTEN_IF_RESUMED) != 0 && (mFlags & FLAG_LISTENING) == 0) {
+                startListening();
+            }
+        } else {
+            mFlags &= ~FLAG_RESUMED;
+        }
+    }
+
+    /**
+     * Updates the listening state of the host. If the host is not resumed, startListening is
+     * deferred until next resume.
+     *
+     * @see #setResumed(boolean)
+     */
+    public void setListenIfResumed(boolean listenIfResumed) {
+        if (!Utilities.ATLEAST_NOUGAT_MR1) {
+            return;
+        }
+        if (listenIfResumed == ((mFlags & FLAG_LISTEN_IF_RESUMED) != 0)) {
+            return;
+        }
+        if (listenIfResumed) {
+            mFlags |= FLAG_LISTEN_IF_RESUMED;
+            if ((mFlags & FLAG_RESUMED) != 0) {
+                // If we are resumed, start listening immediately. Note we do not check for
+                // duplicate calls before calling startListening as startListening is safe to call
+                // multiple times.
+                startListening();
+            }
+        } else {
+            mFlags &= ~FLAG_LISTEN_IF_RESUMED;
+            stopListening();
+        }
+    }
+
     @Override
     public int allocateAppWidgetId() {
         if (FeatureFlags.GO_DISABLE_WIDGETS) {
@@ -203,12 +258,7 @@
     }
 
     private void sendActionCancelled(final BaseActivity activity, final int requestCode) {
-        new Handler().post(new Runnable() {
-            @Override
-            public void run() {
-                activity.onActivityResult(requestCode, Activity.RESULT_CANCELED, null);
-            }
-        });
+        new Handler().post(() -> activity.onActivityResult(requestCode, RESULT_CANCELED, null));
     }
 
     /**
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index 78d753a..928258f 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -45,7 +45,6 @@
     void onPause();
     void onDestroy();
     void onSaveInstanceState(Bundle outState);
-    void onNewIntent(Intent intent);
     void onActivityResult(int requestCode, int resultCode, Intent data);
     void onRequestPermissionsResult(int requestCode, String[] permissions,
             int[] grantResults);
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index f016e8d..1e6016b 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -25,7 +25,6 @@
 import android.os.Looper;
 import android.view.View;
 
-import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.anim.AnimationLayerSet;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -83,6 +82,8 @@
     private StateHandler[] mStateHandlers;
     private LauncherState mState = NORMAL;
 
+    private StateListener mStateListener;
+
     public LauncherStateManager(Launcher l) {
         mUiHandler = new Handler(Looper.getMainLooper());
         mLauncher = l;
@@ -99,6 +100,10 @@
         return mStateHandlers;
     }
 
+    public void setStateListener(StateListener stateListener) {
+        mStateListener = stateListener;
+    }
+
     /**
      * @see #goToState(LauncherState, boolean, Runnable)
      */
@@ -157,6 +162,9 @@
             for (StateHandler handler : getStateHandlers()) {
                 handler.setState(state);
             }
+            if (mStateListener != null) {
+                mStateListener.onStateSetImmediately(state);
+            }
             mLauncher.getUserEventDispatcher().resetElapsedContainerMillis();
 
             // Run any queued runnable
@@ -210,6 +218,17 @@
             public void onAnimationStart(Animator animation) {
                 // Change the internal state only when the transition actually starts
                 setState(state);
+                if (mStateListener != null) {
+                    mStateListener.onStateTransitionStart(state);
+                }
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                if (mStateListener != null) {
+                    mStateListener.onStateTransitionComplete(mState);
+                }
             }
 
             @Override
@@ -230,6 +249,7 @@
         mState.onStateDisabled(mLauncher);
         mState = state;
         mState.onStateEnabled(mLauncher);
+        mLauncher.getAppWidgetHost().setResumed(state == LauncherState.NORMAL);
     }
 
     /**
@@ -304,4 +324,15 @@
         void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
                 AnimatorSet anim, AnimationConfig config);
     }
+
+    public interface StateListener {
+
+        /**
+         * Called when the state is set without an animation.
+         */
+        void onStateSetImmediately(LauncherState state);
+
+        void onStateTransitionStart(LauncherState toState);
+        void onStateTransitionComplete(LauncherState finalState);
+    }
 }
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 4240a30..6c22474 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -93,7 +93,6 @@
     protected int mMinSnapVelocity;
 
     protected boolean mFirstLayout = true;
-    private int mNormalChildHeight;
 
     @ViewDebug.ExportedProperty(category = "launcher")
     protected int mCurrentPage;
@@ -166,8 +165,6 @@
     @Thunk static int REORDERING_REORDER_REPOSITION_DURATION = 300;
     private static int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 80;
 
-    private float mMinScale = 1f;
-    private boolean mUseMinScale = false;
     @Thunk View mDragView;
     private Runnable mSidePageHoverRunnable;
     @Thunk int mSidePageHoverIndex = -1;
@@ -273,12 +270,6 @@
         }
     }
 
-    public void setMinScale(float f) {
-        mMinScale = f;
-        mUseMinScale = true;
-        requestLayout();
-    }
-
     @Override
     public void setScaleX(float scaleX) {
         super.setScaleX(scaleX);
@@ -597,56 +588,9 @@
         computeScrollHelper();
     }
 
-    public static class LayoutParams extends ViewGroup.LayoutParams {
-        public boolean isFullScreenPage = false;
-
-        // If true, the start edge of the page snaps to the start edge of the viewport.
-        public boolean matchStartEdge = false;
-
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(int width, int height) {
-            super(width, height);
-        }
-
-        public LayoutParams(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        public LayoutParams(ViewGroup.LayoutParams source) {
-            super(source);
-        }
-    }
-
-    @Override
-    public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new LayoutParams(getContext(), attrs);
-    }
-
-    @Override
-    protected LayoutParams generateDefaultLayoutParams() {
-        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-    }
-
-    @Override
-    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
-        return new LayoutParams(p);
-    }
-
-    @Override
-    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
-        return p instanceof LayoutParams;
-    }
-
-    public void addFullScreenPage(View page) {
-        LayoutParams lp = generateDefaultLayoutParams();
-        lp.isFullScreenPage = true;
-        super.addView(page, 0, lp);
-    }
-
     public int getNormalChildHeight() {
-        return mNormalChildHeight;
+        return  getViewportHeight() - getPaddingTop() - getPaddingBottom()
+                - mInsets.top - mInsets.bottom;
     }
 
     @Override
@@ -662,22 +606,7 @@
         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
         int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-        // NOTE: We multiply by 2f to account for the fact that depending on the offset of the
-        // viewport, we can be at most one and a half screens offset once we scale down
-        DisplayMetrics dm = getResources().getDisplayMetrics();
-        int maxSize = Math.max(dm.widthPixels + mInsets.left + mInsets.right,
-                dm.heightPixels + mInsets.top + mInsets.bottom);
 
-        int parentWidthSize = (int) (2f * maxSize);
-        int parentHeightSize = (int) (2f * maxSize);
-        int scaledWidthSize, scaledHeightSize;
-        if (mUseMinScale) {
-            scaledWidthSize = (int) (parentWidthSize / mMinScale);
-            scaledHeightSize = (int) (parentHeightSize / mMinScale);
-        } else {
-            scaledWidthSize = widthSize;
-            scaledHeightSize = heightSize;
-        }
         mViewport.set(0, 0, widthSize, heightSize);
 
         if (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED) {
@@ -691,71 +620,19 @@
             return;
         }
 
-        /* Allow the height to be set as WRAP_CONTENT. This allows the particular case
-         * of the All apps view on XLarge displays to not take up more space then it needs. Width
-         * is still not allowed to be set as WRAP_CONTENT since many parts of the code expect
-         * each page to have the same width.
-         */
-        final int verticalPadding = getPaddingTop() + getPaddingBottom();
-        final int horizontalPadding = getPaddingLeft() + getPaddingRight();
-
-        int referenceChildWidth = 0;
         // The children are given the same width and height as the workspace
         // unless they were set to WRAP_CONTENT
         if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
-        if (DEBUG) Log.d(TAG, "PagedView.scaledSize: " + scaledWidthSize + ", " + scaledHeightSize);
-        if (DEBUG) Log.d(TAG, "PagedView.parentSize: " + parentWidthSize + ", " + parentHeightSize);
-        if (DEBUG) Log.d(TAG, "PagedView.horizontalPadding: " + horizontalPadding);
-        if (DEBUG) Log.d(TAG, "PagedView.verticalPadding: " + verticalPadding);
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            // disallowing padding in paged view (just pass 0)
-            final View child = getPageAt(i);
-            if (child.getVisibility() != GONE) {
-                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
 
-                int childWidthMode;
-                int childHeightMode;
-                int childWidth;
-                int childHeight;
+        int myWidthSpec = MeasureSpec.makeMeasureSpec(
+                getViewportWidth() - mInsets.left - mInsets.right, MeasureSpec.EXACTLY);
+        int myHeightSpec = MeasureSpec.makeMeasureSpec(
+                getViewportHeight() - mInsets.top - mInsets.bottom, MeasureSpec.EXACTLY);
 
-                if (!lp.isFullScreenPage) {
-                    if (lp.width == LayoutParams.WRAP_CONTENT) {
-                        childWidthMode = MeasureSpec.AT_MOST;
-                    } else {
-                        childWidthMode = MeasureSpec.EXACTLY;
-                    }
-
-                    if (lp.height == LayoutParams.WRAP_CONTENT) {
-                        childHeightMode = MeasureSpec.AT_MOST;
-                    } else {
-                        childHeightMode = MeasureSpec.EXACTLY;
-                    }
-
-                    childWidth = getViewportWidth() - horizontalPadding
-                            - mInsets.left - mInsets.right;
-                    childHeight = getViewportHeight() - verticalPadding
-                            - mInsets.top - mInsets.bottom;
-                    mNormalChildHeight = childHeight;
-                } else {
-                    childWidthMode = MeasureSpec.EXACTLY;
-                    childHeightMode = MeasureSpec.EXACTLY;
-
-                    childWidth = getViewportWidth();
-                    childHeight = getViewportHeight();
-                }
-                if (referenceChildWidth == 0) {
-                    referenceChildWidth = childWidth;
-                }
-
-                final int childWidthMeasureSpec =
-                        MeasureSpec.makeMeasureSpec(childWidth, childWidthMode);
-                    final int childHeightMeasureSpec =
-                        MeasureSpec.makeMeasureSpec(childHeight, childHeightMode);
-                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-            }
-        }
-        setMeasuredDimension(scaledWidthSize, scaledHeightSize);
+        // measureChildren takes accounts for content padding, we only need to care about extra
+        // space due to insets.
+        measureChildren(myWidthSpec, myHeightSpec);
+        setMeasuredDimension(widthSize, heightSize);
     }
 
     @SuppressLint("DrawAllocation")
@@ -780,10 +657,7 @@
 
         int verticalPadding = getPaddingTop() + getPaddingBottom();
 
-        LayoutParams lp = (LayoutParams) getChildAt(startIndex).getLayoutParams();
-        LayoutParams nextLp;
-
-        int childLeft = offsetX + (lp.isFullScreenPage ? 0 : getPaddingLeft());
+        int childLeft = offsetX + getPaddingLeft();
         if (mPageScrolls == null || childCount != mChildCountOnLastLayout) {
             mPageScrolls = new int[childCount];
         }
@@ -791,14 +665,9 @@
         for (int i = startIndex; i != endIndex; i += delta) {
             final View child = getPageAt(i);
             if (child.getVisibility() != View.GONE) {
-                lp = (LayoutParams) child.getLayoutParams();
-                int childTop;
-                if (lp.isFullScreenPage) {
-                    childTop = offsetY;
-                } else {
-                    childTop = offsetY + getPaddingTop() + mInsets.top;
-                    childTop += (getViewportHeight() - mInsets.top - mInsets.bottom - verticalPadding - child.getMeasuredHeight()) / 2;
-                }
+                int childTop = offsetY + getPaddingTop() + mInsets.top;
+                childTop += (getViewportHeight() - mInsets.top - mInsets.bottom - verticalPadding
+                        - child.getMeasuredHeight()) / 2;
 
                 final int childWidth = child.getMeasuredWidth();
                 final int childHeight = child.getMeasuredHeight();
@@ -807,26 +676,10 @@
                 child.layout(childLeft, childTop,
                         childLeft + child.getMeasuredWidth(), childTop + childHeight);
 
-                int scrollOffsetLeft = lp.isFullScreenPage ? 0 : getPaddingLeft();
+                int scrollOffsetLeft = getPaddingLeft();
                 mPageScrolls[i] = childLeft - scrollOffsetLeft - offsetX;
 
-                int pageGap = mPageSpacing;
-                int next = i + delta;
-                if (next != endIndex) {
-                    nextLp = (LayoutParams) getPageAt(next).getLayoutParams();
-                } else {
-                    nextLp = null;
-                }
-
-                // Prevent full screen pages from showing in the viewport
-                // when they are not the current page.
-                if (lp.isFullScreenPage) {
-                    pageGap = getPaddingLeft();
-                } else if (nextLp != null && nextLp.isFullScreenPage) {
-                    pageGap = getPaddingRight();
-                }
-
-                childLeft += childWidth + pageGap + getChildGap();
+                childLeft += childWidth + mPageSpacing + getChildGap();
             }
         }
 
@@ -1289,12 +1142,7 @@
         } else {
             View child = getChildAt(index);
 
-            int scrollOffset = 0;
-            LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            if (!lp.isFullScreenPage) {
-                scrollOffset = mIsRtl ? getPaddingRight() : getPaddingLeft();
-            }
-
+            int scrollOffset = scrollOffset = mIsRtl ? getPaddingRight() : getPaddingLeft();
             int baselineX = mPageScrolls[index] + scrollOffset + getViewportOffsetX();
             return (int) (child.getX() - baselineX);
         }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 93fe17c..0db5a16 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -80,7 +80,6 @@
 import com.android.launcher3.graphics.PreloadIconDrawable;
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
-import com.android.launcher3.uioverrides.OverviewState;
 import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -440,10 +439,7 @@
         setClipChildren(false);
         setClipToPadding(false);
 
-        // TODO: Remove this
-        setMinScale(OverviewState.SCALE_FACTOR);
         setupLayoutTransition();
-
         mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx);
 
         // Set the wallpaper dimensions when Launcher starts up
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index c843e72..db199c1 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -147,11 +147,12 @@
         // Start home and pass the draw request params
         PinItemDragListener listener = new PinItemDragListener(mRequest, bounds,
                 img.getBitmap().getWidth(), img.getWidth());
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN)
-                .addCategory(Intent.CATEGORY_HOME)
-                .setPackage(getPackageName())
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-                .putExtra(PinItemDragListener.EXTRA_PIN_ITEM_DRAG_LISTENER, listener);
+
+        Intent homeIntent = listener.addToIntent(
+                new Intent(Intent.ACTION_MAIN)
+                        .addCategory(Intent.CATEGORY_HOME)
+                        .setPackage(getPackageName())
+                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
 
         if (!getResources().getBoolean(R.bool.allow_rotation) &&
                 !Utilities.isAllowRotationPrefEnabled(this) &&
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 96aaee0..4629dad 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -16,22 +16,25 @@
 
 package com.android.launcher3.dragndrop;
 
+import static com.android.launcher3.LauncherState.NORMAL;
+
 import android.content.ClipDescription;
 import android.content.Intent;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.Parcel;
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.DragEvent;
 import android.view.View;
 
+import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget.DragObject;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
+import com.android.launcher3.states.InternalStateHandler;
 import com.android.launcher3.widget.PendingItemDragHelper;
 
 import java.util.UUID;
@@ -39,7 +42,7 @@
 /**
  * {@link DragSource} for handling drop from a different window.
  */
-public abstract class BaseItemDragListener implements
+public abstract class BaseItemDragListener extends InternalStateHandler implements
         View.OnDragListener, DragSource, DragOptions.PreDragCondition {
 
     private static final String TAG = "BaseItemDragListener";
@@ -67,25 +70,16 @@
         mId = UUID.randomUUID().toString();
     }
 
-    protected BaseItemDragListener(Parcel parcel) {
-        mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
-        mPreviewBitmapWidth = parcel.readInt();
-        mPreviewViewWidth = parcel.readInt();
-        mId = parcel.readString();
-    }
-
-    protected void writeToParcel(Parcel parcel, int i) {
-        mPreviewRect.writeToParcel(parcel, i);
-        parcel.writeInt(mPreviewBitmapWidth);
-        parcel.writeInt(mPreviewViewWidth);
-        parcel.writeString(mId);
-    }
-
     public String getMimeType() {
         return MIME_TYPE_PREFIX + mId;
     }
 
-    public void setLauncher(Launcher launcher) {
+    @Override
+    public void init(Launcher launcher, boolean alreadyOnHome) {
+        AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
+        launcher.getStateManager().goToState(NORMAL, alreadyOnHome /* animated */);
+        launcher.getDragLayer().setOnDragListener(this);
+
         mLauncher = launcher;
         mDragController = launcher.getDragController();
     }
@@ -182,4 +176,7 @@
             mLauncher.getDragLayer().setOnDragListener(null);
         }
     }
+
+    @Override
+    public void onLauncherResume() { }
 }
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 9402383..818cea7 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -605,29 +605,32 @@
     }
 
     private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
-        final Rect r = mRectTemp;
+        mDragObject.x = x;
+        mDragObject.y = y;
 
+        final Rect r = mRectTemp;
         final ArrayList<DropTarget> dropTargets = mDropTargets;
         final int count = dropTargets.size();
-        for (int i=count-1; i>=0; i--) {
+        for (int i = count - 1; i >= 0; i--) {
             DropTarget target = dropTargets.get(i);
             if (!target.isDropEnabled())
                 continue;
 
             target.getHitRectRelativeToDragLayer(r);
-
-            mDragObject.x = x;
-            mDragObject.y = y;
             if (r.contains(x, y)) {
-
                 dropCoordinates[0] = x;
                 dropCoordinates[1] = y;
                 mLauncher.getDragLayer().mapCoordInSelfToDescendant((View) target, dropCoordinates);
-
                 return target;
             }
         }
-        return null;
+        // Pass all unhandled drag to workspace. Workspace finds the correct
+        // cell layout to drop to in the existing drag/drop logic.
+        dropCoordinates[0] = x;
+        dropCoordinates[1] = y;
+        mLauncher.getDragLayer().mapCoordInSelfToDescendant(mLauncher.getWorkspace(),
+                dropCoordinates);
+        return mLauncher.getWorkspace();
     }
 
     public void setWindowToken(IBinder token) {
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 8189b23..9f9822c 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -703,13 +703,14 @@
     }
 
     @Override
-    public void onChildViewAdded(View parent, View child) {
-        super.onChildViewAdded(parent, child);
+    public void onViewAdded(View child) {
+        super.onViewAdded(child);
         updateChildIndices();
     }
 
     @Override
-    public void onChildViewRemoved(View parent, View child) {
+    public void onViewRemoved(View child) {
+        super.onViewRemoved(child);
         updateChildIndices();
     }
 
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index b9d97ac..924bb4c 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -18,23 +18,18 @@
 
 import android.annotation.TargetApi;
 import android.appwidget.AppWidgetManager;
-import android.content.Intent;
 import android.content.pm.LauncherApps.PinItemRequest;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.view.DragEvent;
 import android.view.View;
 import android.widget.RemoteViews;
 
 import com.android.launcher3.DragSource;
 import com.android.launcher3.ItemInfo;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.PendingAddItemInfo;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -46,9 +41,7 @@
  * in the source window and is passed on to the Launcher activity as an Intent extra.
  */
 @TargetApi(Build.VERSION_CODES.O)
-public class PinItemDragListener extends BaseItemDragListener implements Parcelable {
-
-    public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
+public class PinItemDragListener extends BaseItemDragListener {
 
     private final PinItemRequest mRequest;
 
@@ -58,22 +51,6 @@
         mRequest = request;
     }
 
-    private PinItemDragListener(Parcel parcel) {
-        super(parcel);
-        mRequest = PinItemRequest.CREATOR.createFromParcel(parcel);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel parcel, int i) {
-        super.writeToParcel(parcel, i);
-        mRequest.writeToParcel(parcel, i);
-    }
-
     @Override
     protected boolean onDragStart(DragEvent event) {
         if (!mRequest.isValid()) {
@@ -126,33 +103,4 @@
         }
         return null;
     }
-
-    public static boolean handleDragRequest(Launcher launcher, Intent intent) {
-        if (!Utilities.ATLEAST_OREO) {
-            return false;
-        }
-        if (intent == null || !Intent.ACTION_MAIN.equals(intent.getAction())) {
-            return false;
-        }
-        Parcelable dragExtra = intent.getParcelableExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
-        if (dragExtra instanceof PinItemDragListener) {
-            PinItemDragListener dragListener = (PinItemDragListener) dragExtra;
-            dragListener.setLauncher(launcher);
-
-            launcher.getDragLayer().setOnDragListener(dragListener);
-            return true;
-        }
-        return false;
-    }
-
-    public static final Parcelable.Creator<PinItemDragListener> CREATOR =
-            new Parcelable.Creator<PinItemDragListener>() {
-                public PinItemDragListener createFromParcel(Parcel source) {
-                    return new PinItemDragListener(source);
-                }
-
-                public PinItemDragListener[] newArray(int size) {
-                    return new PinItemDragListener[size];
-                }
-            };
 }
diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java
index c6feefc..f084fd2 100644
--- a/src/com/android/launcher3/states/InternalStateHandler.java
+++ b/src/com/android/launcher3/states/InternalStateHandler.java
@@ -17,42 +17,52 @@
 
 import android.content.Intent;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.Launcher.OnResumeCallback;
 
 /**
- * Utility class to sending state handling logic to Launcher from within the same process
+ * Utility class to sending state handling logic to Launcher from within the same process.
+ *
+ * Extending {@link Binder} ensures that the platform maintains a single instance of each object
+ * which allows this object to safely navigate the system process.
  */
 public abstract class InternalStateHandler extends Binder implements OnResumeCallback {
 
     public static final String EXTRA_STATE_HANDLER = "launcher.state_handler";
 
-    public abstract void onCreate(Launcher launcher);
-    public abstract void onNewIntent(Launcher launcher, boolean alreadyOnHome);
+    protected abstract void init(Launcher launcher, boolean alreadyOnHome);
 
-    public static void handleCreate(Launcher launcher, Intent intent) {
-        if (intent.getExtras() != null) {
-            IBinder stateBinder = intent.getExtras().getBinder(EXTRA_STATE_HANDLER);
-            if (stateBinder instanceof InternalStateHandler) {
-                InternalStateHandler handler = (InternalStateHandler) stateBinder;
-                launcher.setOnResumeCallback(handler);
-                handler.onCreate(launcher);
-            }
-            intent.getExtras().remove(EXTRA_STATE_HANDLER);
-        }
+    public final Intent addToIntent(Intent intent) {
+        Bundle extras = new Bundle();
+        extras.putBinder(EXTRA_STATE_HANDLER, this);
+        intent.putExtras(extras);
+        return intent;
     }
 
-    public static void handleNewIntent(Launcher launcher, Intent intent, boolean alreadyOnHome) {
-        if (intent.getExtras() != null) {
+    public static boolean handleCreate(Launcher launcher, Intent intent) {
+        return handleIntent(launcher, intent, false);
+    }
+
+    public static boolean handleNewIntent(Launcher launcher, Intent intent, boolean alreadyOnHome) {
+        return handleIntent(launcher, intent, alreadyOnHome);
+    }
+
+    private static boolean handleIntent(
+            Launcher launcher, Intent intent, boolean alreadyOnHome) {
+        boolean result = false;
+        if (intent != null && intent.getExtras() != null) {
             IBinder stateBinder = intent.getExtras().getBinder(EXTRA_STATE_HANDLER);
             if (stateBinder instanceof InternalStateHandler) {
                 InternalStateHandler handler = (InternalStateHandler) stateBinder;
                 launcher.setOnResumeCallback(handler);
-                handler.onNewIntent(launcher, alreadyOnHome);
+                handler.init(launcher, alreadyOnHome);
+                result = true;
             }
             intent.getExtras().remove(EXTRA_STATE_HANDLER);
         }
+        return result;
     }
 }
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java
index c339634..dcf7453 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java
@@ -34,7 +34,7 @@
 public class OverviewState extends LauncherState {
 
     // The percent to shrink the workspace during overview mode
-    public static final float SCALE_FACTOR = 0.7f;
+    private static final float SCALE_FACTOR = 0.7f;
 
     private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_MULTI_PAGE;