Merge "Reporting range of visible tasks" into ub-launcher3-edmonton
diff --git a/Android.mk b/Android.mk
index dbafcbc..ab445ac 100644
--- a/Android.mk
+++ b/Android.mk
@@ -173,7 +173,57 @@
 
 include $(BUILD_PACKAGE)
 
+#
+# Build rule for Launcher3 Go app with quickstep for Android Go devices.
+#
+include $(CLEAR_VARS)
 
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-v4 \
+    android-support-v7-recyclerview \
+    android-support-dynamic-animation \
+    libSharedSystemUI
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src) \
+    $(call all-java-files-under, quickstep/src) \
+    $(call all-java-files-under, go/src_flags) \
+    $(call all-proto-files-under, protos) \
+    $(call all-proto-files-under, proto_overrides)
+
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/quickstep/res \
+    $(LOCAL_PATH)/go/res \
+    $(LOCAL_PATH)/res \
+    prebuilts/sdk/current/support/v7/recyclerview/res \
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ --proto_path=$(LOCAL_PATH)/proto_overrides/
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java
+
+LOCAL_AAPT_FLAGS := \
+    --auto-add-overlay \
+    --extra-packages android.support.v7.recyclerview \
+
+LOCAL_SDK_VERSION := system_current
+LOCAL_MIN_SDK_VERSION := 26
+LOCAL_PACKAGE_NAME := Launcher3QuickStepGo
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3
+
+LOCAL_FULL_LIBS_MANIFEST_FILES := \
+    $(LOCAL_PATH)/go/AndroidManifest.xml \
+    $(LOCAL_PATH)/AndroidManifest.xml \
+    $(LOCAL_PATH)/AndroidManifest-common.xml
+
+LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
+LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.*
+
+include $(BUILD_PACKAGE)
 
 
 # ==================================================
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index cab20a3..06e6a92 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -110,6 +110,8 @@
   QUICK_SCRUB_BUTTON = 12;
   CLEAR_ALL_BUTTON = 13;
   CANCEL_TARGET = 14;
+  TASK_PREVIEW = 15;
+  SPLIT_SCREEN_TARGET = 16;
 }
 
 enum TipType {
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 6703bb5..eea71ca 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -50,6 +50,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.Log;
@@ -105,6 +106,7 @@
     private static final int APP_LAUNCH_ALPHA_DURATION = 50;
 
     public static final int RECENTS_LAUNCH_DURATION = 336;
+    public static final int RECENTS_QUICKSCRUB_LAUNCH_DURATION = 300;
     private static final int LAUNCHER_RESUME_START_DELAY = 100;
     private static final int CLOSING_TRANSITION_DURATION_MS = 250;
 
@@ -236,8 +238,14 @@
         return bounds;
     }
 
-    public void setRemoteAnimationProvider(RemoteAnimationProvider animationProvider) {
+    public void setRemoteAnimationProvider(final RemoteAnimationProvider animationProvider,
+            CancellationSignal cancellationSignal) {
         mRemoteAnimationProvider = animationProvider;
+        cancellationSignal.setOnCancelListener(() -> {
+            if (animationProvider == mRemoteAnimationProvider) {
+                mRemoteAnimationProvider = null;
+            }
+        });
     }
 
     /**
@@ -253,15 +261,21 @@
         RecentsView recentsView = mLauncher.getOverviewPanel();
         boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING);
         boolean skipLauncherChanges = !launcherClosing;
+        boolean isLaunchingFromQuickscrub =
+                recentsView.getQuickScrubController().isWaitingForTaskLaunch();
 
         TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
         if (taskView == null) {
             return false;
         }
 
+        int duration = isLaunchingFromQuickscrub
+                ? RECENTS_QUICKSCRUB_LAUNCH_DURATION
+                : RECENTS_LAUNCH_DURATION;
+
         ClipAnimationHelper helper = new ClipAnimationHelper();
         target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper)
-                .setDuration(RECENTS_LAUNCH_DURATION));
+                .setDuration(duration));
 
         Animator childStateAnimation = null;
         // Found a visible recents task that matches the opening app, lets launch the app from there
@@ -270,7 +284,7 @@
         if (launcherClosing) {
             launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper);
             launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
-            launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
+            launcherAnim.setDuration(duration);
 
             // Make sure recents gets fixed up by resetting task alphas and scales, etc.
             windowAnimEndListener = new AnimatorListenerAdapter() {
@@ -282,11 +296,10 @@
             };
         } else {
             AnimatorPlaybackController controller =
-                    mLauncher.getStateManager()
-                            .createAnimationToNewWorkspace(NORMAL, RECENTS_LAUNCH_DURATION);
+                    mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration);
             controller.dispatchOnStart();
             childStateAnimation = controller.getTarget();
-            launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
+            launcherAnim = controller.getAnimationPlayer().setDuration(duration);
             windowAnimEndListener = new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java
index e5e377f..08b6bfc 100644
--- a/quickstep/src/com/android/launcher3/LauncherInitListener.java
+++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 
 import com.android.launcher3.states.InternalStateHandler;
@@ -48,10 +49,11 @@
 
             // Set a one-time animation provider. After the first call, this will get cleared.
             // TODO: Probably also check the intended target id.
+            CancellationSignal cancellationSignal = new CancellationSignal();
             appTransitionManager.setRemoteAnimationProvider((targets) -> {
 
                 // On the first call clear the reference.
-                appTransitionManager.setRemoteAnimationProvider(null);
+                cancellationSignal.cancel();
                 RemoteAnimationProvider provider = mRemoteAnimationProvider;
                 mRemoteAnimationProvider = null;
 
@@ -59,7 +61,7 @@
                     return provider.createWindowAnimation(targets);
                 }
                 return null;
-            });
+            }, cancellationSignal);
         }
         OverviewCallbacks.get(launcher).onInitOverviewTransition();
         return mOnInitListener.test(launcher, alreadyOnHome);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
index 43d9822..cd92314 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java
@@ -76,4 +76,10 @@
         return Math.min(Math.min(dp.availableHeightPx / usedHeight,
                 dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP);
     }
+
+    @Override
+    public void onStateDisabled(Launcher launcher) {
+        super.onStateDisabled(launcher);
+        launcher.<RecentsView>getOverviewPanel().getQuickScrubController().cancelActiveQuickscrub();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index e3aabd6..ea27eb2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -76,15 +76,16 @@
         }
         PropertySetter setter = config.getPropertySetter(builder);
         float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher);
-        Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
-        setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0], scaleInterpolator);
-        Interpolator transYInterpolator = scaleInterpolator;
+        Interpolator scaleAndTransYInterpolator = builder.getInterpolator(
+                ANIM_OVERVIEW_SCALE, LINEAR);
         if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
-            transYInterpolator = Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0,
-                    QUICK_SCRUB_TRANSLATION_Y_FACTOR);
+            scaleAndTransYInterpolator = Interpolators.clampToProgress(
+                    QUICK_SCRUB_START_INTERPOLATOR, 0, QUICK_SCRUB_TRANSLATION_Y_FACTOR);
         }
+        setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleTranslationYFactor[0],
+                scaleAndTransYInterpolator);
         setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1],
-                transYInterpolator);
+                scaleAndTransYInterpolator);
         setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0,
                 builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index d0c7b21..dd5dcbe 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -25,14 +25,19 @@
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
 import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.content.Context;
+import android.os.CancellationSignal;
 import android.util.Base64;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppTransitionManagerImpl;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.LauncherStateManager;
 import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -41,6 +46,8 @@
 import com.android.launcher3.util.TouchController;
 import com.android.quickstep.OverviewInteractionState;
 import com.android.quickstep.RecentsModel;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
+import com.android.quickstep.util.RemoteFadeOutAnimationListener;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.ActivityCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -179,6 +186,23 @@
         }
     }
 
+    public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
+            CancellationSignal cancellationSignal) {
+        LauncherAppTransitionManagerImpl appTransitionManager =
+                (LauncherAppTransitionManagerImpl) launcher.getAppTransitionManager();
+        appTransitionManager.setRemoteAnimationProvider((targets) -> {
+
+            // On the first call clear the reference.
+            cancellationSignal.cancel();
+
+            ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
+            fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(targets));
+            AnimatorSet anim = new AnimatorSet();
+            anim.play(fadeAnimation);
+            return anim;
+        }, cancellationSignal);
+    }
+
     public static boolean dumpActivity(Activity activity, PrintWriter writer) {
         if (!Utilities.IS_DEBUG_DEVICE) {
             return false;
diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java
index 8e1a3d5..7a79c6f 100644
--- a/quickstep/src/com/android/quickstep/QuickScrubController.java
+++ b/quickstep/src/com/android/quickstep/QuickScrubController.java
@@ -40,7 +40,7 @@
 public class QuickScrubController implements OnAlarmListener {
 
     public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240;
-    public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 150;
+    public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 200;
     // We want the translation y to finish faster than the rest of the animation.
     public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6;
     public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN;
@@ -132,6 +132,17 @@
         }
     }
 
+    public void cancelActiveQuickscrub() {
+        if (!mInQuickScrub) {
+            return;
+        }
+        Log.d(TAG, "Quickscrub was active, cancelling");
+        mInQuickScrub = false;
+        mActivityControlHelper = null;
+        mOnFinishedTransitionToQuickScrubRunnable = null;
+        mRecentsView.setNextPageSwitchRunnable(null);
+    }
+
     /**
      * Initializes the UI for quick scrub, returns true if success.
      */
@@ -145,6 +156,10 @@
         return true;
     }
 
+    public boolean isWaitingForTaskLaunch() {
+        return mWaitingForTaskLaunch;
+    }
+
     /**
      * Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction.
      */
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
index 228af8e..f82ff8c 100644
--- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
@@ -16,6 +16,8 @@
 
 package com.android.quickstep;
 
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
+
 import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -35,6 +37,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutInfo;
 import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.util.InstantAppResolver;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskThumbnailView;
@@ -166,7 +169,8 @@
                         Log.w(TAG, "Failed to notify SysUI of split screen: ", e);
                         return;
                     }
-
+                    activity.getUserEventDispatcher().logActionOnControl(TAP,
+                            LauncherLogProto.ControlType.SPLIT_SCREEN_TARGET);
                     // Add a device profile change listener to kick off animating the side tasks
                     // once we enter multiwindow mode and relayout
                     activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener);
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 191c237..d171f69 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -700,6 +700,7 @@
 
         mRecentsView.setRunningTaskHidden(false);
         mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
+        mQuickScrubController.cancelActiveQuickscrub();
     }
 
     private void notifyTransitionCancelled() {
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index cc24f1d..a654482 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -227,12 +227,16 @@
         dl.getDescendantRectRelativeToSelf(ttv, targetRect.rect);
         updateTargetRect(targetRect);
 
-        // Transform the clip relative to the target rect.
-        float scale = mTargetRect.width() / mSourceRect.width();
-        mSourceWindowClipInsets.left = mSourceWindowClipInsets.left * scale;
-        mSourceWindowClipInsets.top = mSourceWindowClipInsets.top * scale;
-        mSourceWindowClipInsets.right = mSourceWindowClipInsets.right * scale;
-        mSourceWindowClipInsets.bottom = mSourceWindowClipInsets.bottom * scale;
+        if (target == null) {
+            // Transform the clip relative to the target rect. Only do this in the case where we
+            // aren't applying the insets to the app windows (where the clip should be in target app
+            // space)
+            float scale = mTargetRect.width() / mSourceRect.width();
+            mSourceWindowClipInsets.left = mSourceWindowClipInsets.left * scale;
+            mSourceWindowClipInsets.top = mSourceWindowClipInsets.top * scale;
+            mSourceWindowClipInsets.right = mSourceWindowClipInsets.right * scale;
+            mSourceWindowClipInsets.bottom = mSourceWindowClipInsets.bottom * scale;
+        }
     }
 
     private void updateStackBoundsToMultiWindowTaskSize(BaseDraggingActivity activity) {
diff --git a/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java b/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java
new file mode 100644
index 0000000..40dd74b
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/RemoteFadeOutAnimationListener.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.quickstep.util.RemoteAnimationProvider.prepareTargetsForFirstFrame;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.TransactionCompat;
+
+/**
+ * Animation listener which fades out the closing targets
+ */
+public class RemoteFadeOutAnimationListener implements AnimatorUpdateListener {
+
+    private final RemoteAnimationTargetSet mTarget;
+    private boolean mFirstFrame = true;
+
+    public RemoteFadeOutAnimationListener(RemoteAnimationTargetCompat[] targets) {
+        mTarget = new RemoteAnimationTargetSet(targets, MODE_CLOSING);
+    }
+
+    @Override
+    public void onAnimationUpdate(ValueAnimator valueAnimator) {
+        TransactionCompat t = new TransactionCompat();
+        if (mFirstFrame) {
+            prepareTargetsForFirstFrame(mTarget.unfilteredApps, t, MODE_CLOSING);
+            mFirstFrame = false;
+        }
+
+        float alpha = 1 - valueAnimator.getAnimatedFraction();
+        for (RemoteAnimationTargetCompat app : mTarget.apps) {
+            t.setAlpha(app.leash, alpha);
+        }
+        t.apply();
+    }
+}
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 631626f..2b760f3 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -45,7 +45,7 @@
 
     <style name="LauncherTheme" parent="@style/BaseLauncherThemeWithCustomAttrs"></style>
 
-    <style name="LauncherThemeDarkText" parent="@style/LauncherTheme">
+    <style name="LauncherTheme.DarkText" parent="@style/LauncherTheme">
         <item name="workspaceTextColor">#FF212121</item>
         <item name="workspaceShadowColor">@android:color/transparent</item>
         <item name="workspaceAmbientShadowColor">@android:color/transparent</item>
@@ -70,6 +70,15 @@
         <item name="isMainColorDark">true</item>
     </style>
 
+    <style name="LauncherThemeDark.DarKText" parent="@style/LauncherThemeDark">
+        <item name="workspaceTextColor">#FF212121</item>
+        <item name="workspaceShadowColor">@android:color/transparent</item>
+        <item name="workspaceAmbientShadowColor">@android:color/transparent</item>
+        <item name="workspaceKeyShadowColor">@android:color/transparent</item>
+        <item name="isWorkspaceDarkText">true</item>
+        <item name="workspaceStatusBarScrim">@null</item>
+    </style>
+
     <!--
     Theme overrides to element on homescreen, i.e., which are drawn on top on wallpaper.
     Various foreground colors are overridden to be workspaceTextColor so that they are properly
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index d9e7d20..8af9acc 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -90,11 +90,11 @@
 
     protected int getThemeRes(WallpaperColorInfo wallpaperColorInfo) {
         if (wallpaperColorInfo.isDark()) {
-            return R.style.LauncherThemeDark;
-        } else if (wallpaperColorInfo.supportsDarkText()) {
-            return R.style.LauncherThemeDarkText;
+            return wallpaperColorInfo.supportsDarkText() ?
+                    R.style.LauncherThemeDark_DarKText : R.style.LauncherThemeDark;
         } else {
-            return R.style.LauncherTheme;
+            return wallpaperColorInfo.supportsDarkText() ?
+                    R.style.LauncherTheme_DarkText : R.style.LauncherTheme;
         }
     }
 
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index f938e24..b5eef8b 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -348,20 +348,15 @@
             }
 
             @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                for (int i = mListeners.size() - 1; i >= 0; i--) {
-                    mListeners.get(i).onStateTransitionComplete(state);
-                }
-            }
-
-            @Override
             public void onAnimationSuccess(Animator animator) {
                 // Run any queued runnables
                 if (onCompleteRunnable != null) {
                     onCompleteRunnable.run();
                 }
                 onStateTransitionEnd(state);
+                for (int i = mListeners.size() - 1; i >= 0; i--) {
+                    mListeners.get(i).onStateTransitionComplete(state);
+                }
             }
         });
         mConfig.setAnimation(animation, state);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 7e652cb..66fb3c6 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1533,6 +1533,14 @@
 
     public DragView beginDragShared(View child, DragSource source, ItemInfo dragObject,
             DragPreviewProvider previewProvider, DragOptions dragOptions) {
+        float iconScale = 1f;
+        if (child instanceof BubbleTextView) {
+            Drawable icon = ((BubbleTextView) child).getIcon();
+            if (icon instanceof FastBitmapDrawable) {
+                iconScale = ((FastBitmapDrawable) icon).getAnimatedScale();
+            }
+        }
+
         child.clearFocus();
         child.setPressed(false);
         mOutlineProvider = previewProvider;
@@ -1584,7 +1592,7 @@
         }
 
         DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source,
-                dragObject, dragVisualizeOffset, dragRect, scale, dragOptions);
+                dragObject, dragVisualizeOffset, dragRect, scale * iconScale, scale, dragOptions);
         dv.setIntrinsicIconScaleFactor(dragOptions.intrinsicIconScaleFactor);
         return dv;
     }
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 68ad6e3..72ba418 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -466,9 +466,12 @@
      */
     public void addSpringFromFlingUpdateListener(ValueAnimator animator, float velocity) {
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            boolean shouldSpring = true;
+
             @Override
             public void onAnimationUpdate(ValueAnimator valueAnimator) {
-                if (valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
+                if (shouldSpring
+                        && valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
                     int searchViewId = getSearchView().getId();
                     addSpringView(searchViewId);
 
@@ -481,7 +484,7 @@
                                 }
                             });
 
-                    animator.removeUpdateListener(this);
+                    shouldSpring = false;
                 }
             }
         });
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index df4a7c1..1e84b41 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -159,7 +159,7 @@
         postCleanup();
     }
 
-    private void postCleanup() {
+    protected void postCleanup() {
         clearReference();
         if (mLauncher != null) {
             // Remove any drag params from the launcher intent since the drag operation is complete.
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 5c6946c..8a216fc 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -138,7 +138,7 @@
      */
     public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
             DragSource source, ItemInfo dragInfo, Point dragOffset, Rect dragRegion,
-            float initialDragViewScale, DragOptions options) {
+            float initialDragViewScale, float dragViewScaleOnDrop, DragOptions options) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
         }
@@ -169,7 +169,7 @@
         final float scaleDps = mIsInPreDrag
                 ? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;
         final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
-                registrationY, initialDragViewScale, scaleDps);
+                registrationY, initialDragViewScale, dragViewScaleOnDrop, scaleDps);
         dragView.setItemInfo(dragInfo);
         mDragObject.dragComplete = false;
         if (mOptions.isAccessibleDrag) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 1e5f854..551567a 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -89,6 +89,7 @@
     private final int mRegistrationX;
     private final int mRegistrationY;
     private final float mInitialScale;
+    private final float mScaleOnDrop;
     private final int[] mTempLoc = new int[2];
 
     private Point mDragVisualizeOffset = null;
@@ -131,7 +132,7 @@
      * @param registrationY The y coordinate of the registration point.
      */
     public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
-                    final float initialScale, final float finalScaleDps) {
+                    final float initialScale, final float scaleOnDrop, final float finalScaleDps) {
         super(launcher);
         mLauncher = launcher;
         mDragLayer = launcher.getDragLayer();
@@ -180,6 +181,7 @@
         mRegistrationY = registrationY;
 
         mInitialScale = initialScale;
+        mScaleOnDrop = scaleOnDrop;
 
         // Force a measure, because Workspace uses getMeasuredHeight() before the layout pass
         int ms = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
@@ -596,7 +598,7 @@
     public void animateTo(int toTouchX, int toTouchY, Runnable onCompleteRunnable, int duration) {
         mTempLoc[0] = toTouchX - mRegistrationX;
         mTempLoc[1] = toTouchY - mRegistrationY;
-        mDragLayer.animateViewIntoPosition(this, mTempLoc, 1f, mInitialScale, mInitialScale,
+        mDragLayer.animateViewIntoPosition(this, mTempLoc, 1f, mScaleOnDrop, mScaleOnDrop,
                 DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
     }
 
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index 924bb4c..07eb0d6 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -22,14 +22,17 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 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.uioverrides.UiFactory;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -44,11 +47,13 @@
 public class PinItemDragListener extends BaseItemDragListener {
 
     private final PinItemRequest mRequest;
+    private final CancellationSignal mCancelSignal;
 
     public PinItemDragListener(PinItemRequest request, Rect previewRect,
             int previewBitmapWidth, int previewViewWidth) {
         super(previewRect, previewBitmapWidth, previewViewWidth);
         mRequest = request;
+        mCancelSignal = new CancellationSignal();
     }
 
     @Override
@@ -60,6 +65,15 @@
     }
 
     @Override
+    public boolean init(Launcher launcher, boolean alreadyOnHome) {
+        super.init(launcher, alreadyOnHome);
+        if (!alreadyOnHome) {
+            UiFactory.useFadeOutAnimationForLauncherStart(launcher, mCancelSignal);
+        }
+        return false;
+    }
+
+    @Override
     protected PendingItemDragHelper createDragHelper() {
         final PendingAddItemInfo item;
         if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
@@ -95,6 +109,12 @@
         targetParent.containerType = LauncherLogProto.ContainerType.PINITEM;
     }
 
+    @Override
+    protected void postCleanup() {
+        super.postCleanup();
+        mCancelSignal.cancel();
+    }
+
     public static RemoteViews getPreview(PinItemRequest request) {
         Bundle extras = request.getExtras();
         if (extras != null &&
diff --git a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
index bd5c06e..fde220c 100644
--- a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
+++ b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
@@ -18,7 +18,6 @@
 
 import android.graphics.Rect;
 import android.view.View;
-import android.view.View.OnFocusChangeListener;
 
 import com.android.launcher3.PagedView;
 
@@ -52,8 +51,8 @@
 
     private void computeLocationRelativeToContainer(View child, Rect outRect) {
         View parent = (View) child.getParent();
-        outRect.left += child.getLeft();
-        outRect.top += child.getTop();
+        outRect.left += child.getX();
+        outRect.top += child.getY();
 
         if (parent != mContainer) {
             if (parent instanceof PagedView) {
@@ -64,22 +63,4 @@
             computeLocationRelativeToContainer(parent, outRect);
         }
     }
-
-    /**
-     * Sets the alpha of this FocusIndicatorHelper to 0 when a view with this listener
-     * receives focus.
-     */
-    public View.OnFocusChangeListener getHideIndicatorOnFocusListener() {
-        return new OnFocusChangeListener() {
-            @Override
-            public void onFocusChange(View v, boolean hasFocus) {
-                if (hasFocus) {
-                    endCurrentAnimation();
-                    setCurrentView(null);
-                    setAlpha(0);
-                    invalidateDirty();
-                }
-            }
-        };
-    }
 }
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index aa5b785..74ab14f 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -149,7 +149,7 @@
 
         // Start the drag
         launcher.getDragController().startDrag(preview, dragLayerX, dragLayerY, source, mAddInfo,
-                dragOffset, dragRegion, scale, options);
+                dragOffset, dragRegion, scale, scale, options);
     }
 
     @Override
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index db98f9a..5a7e50f 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.os.CancellationSignal;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -51,6 +52,9 @@
 
     public static void onTrimMemory(Launcher launcher, int level) { }
 
+    public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
+            CancellationSignal cancellationSignal) { }
+
     public static boolean dumpActivity(Activity activity, PrintWriter writer) {
         return false;
     }