Merge "Fixing crash on keyboard shortcuts popup" into ub-launcher3-edmonton
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index f16e4d0..b343cc2 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 1e81ef9..cf62e2e 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -25,6 +25,7 @@
 import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
 import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
 import static com.android.quickstep.TaskUtils.findTaskViewToLaunch;
 import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator;
 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
@@ -62,6 +63,8 @@
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.graphics.DrawableFactory;
 import com.android.launcher3.shortcuts.DeepShortcutView;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.quickstep.util.ClipAnimationHelper;
 import com.android.quickstep.util.MultiValueUpdateListener;
 import com.android.quickstep.util.RemoteAnimationProvider;
@@ -105,8 +108,9 @@
     // Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down.
     public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f;
 
-    private final DragLayer mDragLayer;
     private final Launcher mLauncher;
+    private final DragLayer mDragLayer;
+    private final AlphaProperty mDragLayerAlpha;
 
     private final Handler mHandler;
     private final boolean mIsRtl;
@@ -142,6 +146,7 @@
     public LauncherAppTransitionManagerImpl(Context context) {
         mLauncher = Launcher.getLauncher(context);
         mDragLayer = mLauncher.getDragLayer();
+        mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS);
         mHandler = new Handler(Looper.getMainLooper());
         mIsRtl = Utilities.isRtl(mLauncher.getResources());
         mDeviceProfile = mLauncher.getDeviceProfile();
@@ -325,16 +330,15 @@
                 appsView.setLayerType(View.LAYER_TYPE_NONE, null);
             };
         } else {
-            View contentView = mLauncher.getDragLayer();
-            contentView.setAlpha(alphas[0]);
-            contentView.setTranslationY(trans[0]);
-
-            ObjectAnimator alpha = ObjectAnimator.ofFloat(contentView, View.ALPHA, alphas);
+            mDragLayerAlpha.setValue(alphas[0]);
+            ObjectAnimator alpha =
+                    ObjectAnimator.ofFloat(mDragLayerAlpha, MultiValueAlpha.VALUE, alphas);
             alpha.setDuration(217);
             alpha.setInterpolator(LINEAR);
             launcherAnimator.play(alpha);
 
-            ObjectAnimator transY = ObjectAnimator.ofFloat(contentView, View.TRANSLATION_Y, trans);
+            mDragLayer.setTranslationY(trans[0]);
+            ObjectAnimator transY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, trans);
             transY.setInterpolator(AGGRESSIVE_EASE);
             transY.setDuration(350);
             launcherAnimator.play(transY);
@@ -342,11 +346,9 @@
             mDragLayer.getScrim().hideSysUiScrim(true);
             // Pause page indicator animations as they lead to layer trashing.
             mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
-            contentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
 
-            endListener = () -> {
-                resetContentView(contentView);
-            };
+            endListener = this::resetContentView;
         }
         return new Pair<>(launcherAnimator, endListener);
     }
@@ -700,14 +702,13 @@
         } else {
             AnimatorSet workspaceAnimator = new AnimatorSet();
 
-            View contentView = mLauncher.getRootView();
-
-            contentView.setTranslationY(-mWorkspaceTransY);;
-            workspaceAnimator.play(ObjectAnimator.ofFloat(contentView, View.TRANSLATION_Y,
+            mDragLayer.setTranslationY(-mWorkspaceTransY);;
+            workspaceAnimator.play(ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y,
                     -mWorkspaceTransY, 0));
 
-            contentView.setAlpha(0);
-            workspaceAnimator.play(ObjectAnimator.ofFloat(contentView, View.ALPHA, 0, 1f));
+            mDragLayerAlpha.setValue(0);
+            workspaceAnimator.play(ObjectAnimator.ofFloat(
+                    mDragLayerAlpha, MultiValueAlpha.VALUE, 0, 1f));
 
             workspaceAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY);
             workspaceAnimator.setDuration(333);
@@ -717,25 +718,24 @@
 
             // Pause page indicator animations as they lead to layer trashing.
             mLauncher.getWorkspace().getPageIndicator().pauseAnimations();
-            contentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
 
             workspaceAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    resetContentView(contentView);
+                    resetContentView();
                 }
             });
             anim.play(workspaceAnimator);
         }
     }
 
-    private void resetContentView(View v) {
-        v.setLayerType(View.LAYER_TYPE_NONE, null);
-
+    private void resetContentView() {
         mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd();
-        v.setAlpha(1f);
-        v.setTranslationY(0f);
-        mLauncher.getDragLayer().getScrim().hideSysUiScrim(false);
+        mDragLayerAlpha.setValue(1f);
+        mDragLayer.setLayerType(View.LAYER_TYPE_NONE, null);
+        mDragLayer.setTranslationY(0f);
+        mDragLayer.getScrim().hideSysUiScrim(false);
     }
 
     private boolean hasControlRemoteAppTransitionPermission() {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
index ce8192f..68773b4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java
@@ -15,7 +15,6 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.quickstep.RecentsModel;
-import com.android.quickstep.util.SysuiEventLogger;
 
 /**
  * Touch controller for handling edge swipes in landscape/seascape UI
@@ -75,7 +74,6 @@
         super.onSwipeInteractionCompleted(targetState, logAction);
         if (mFromState == NORMAL && targetState == OVERVIEW) {
             RecentsModel.getInstance(mLauncher).onOverviewShown(true, TAG);
-            SysuiEventLogger.writeDummyRecentsTransition(0);
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
index 514c0e8..1d9ad91 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java
@@ -41,7 +41,6 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.TouchInteractionService;
-import com.android.quickstep.util.SysuiEventLogger;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 
@@ -210,7 +209,6 @@
         super.onSwipeInteractionCompleted(targetState, logAction);
         if (mFromState == NORMAL && targetState == OVERVIEW) {
             RecentsModel.getInstance(mLauncher).onOverviewShown(true, TAG);
-            SysuiEventLogger.writeDummyRecentsTransition(0);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 28384e5..f9dcee0 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep;
 
+import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
 import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
@@ -24,10 +25,15 @@
 
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.annotation.TargetApi;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Handler;
+import android.os.Looper;
 import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.view.View;
@@ -41,6 +47,8 @@
 import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.util.RemoteAnimationProvider;
 import com.android.quickstep.util.RemoteAnimationTargetSet;
@@ -50,21 +58,23 @@
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
+import java.util.Objects;
 import java.util.function.BiPredicate;
 import java.util.function.Consumer;
 
 /**
  * Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
  */
+@TargetApi(Build.VERSION_CODES.P)
 public interface ActivityControlHelper<T extends BaseDraggingActivity> {
 
     LayoutListener createLayoutListener(T activity);
 
     /**
      * Updates the UI to indicate quick interaction.
-     * @return true if there any any UI change as a result of this
      */
-    boolean onQuickInteractionStart(T activity, boolean activityVisible);
+    void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo,
+            boolean activityVisible);
 
     float getTranslationYForQuickScrub(T activity);
 
@@ -103,6 +113,8 @@
 
     boolean supportsLongSwipe(T activity);
 
+    AlphaProperty getAlphaProperty(T activity);
+
     /**
      * Must return a non-null controller is supportsLongSwipe was true.
      */
@@ -116,10 +128,14 @@
         }
 
         @Override
-        public boolean onQuickInteractionStart(Launcher activity, boolean activityVisible) {
+        public void onQuickInteractionStart(Launcher activity, RunningTaskInfo taskInfo,
+                boolean activityVisible) {
             LauncherState fromState = activity.getStateManager().getState();
             activity.getStateManager().goToState(FAST_OVERVIEW, activityVisible);
-            return !fromState.overviewUi;
+
+            QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
+                    .getQuickScrubController();
+            controller.onQuickScrubStart(activityVisible && !fromState.overviewUi, this);
         }
 
         @Override
@@ -298,14 +314,36 @@
             }
             return new LongSwipeHelper(activity, targetSet);
         }
+
+        @Override
+        public AlphaProperty getAlphaProperty(Launcher activity) {
+            return activity.getDragLayer().getAlphaProperty(DragLayer.ALPHA_INDEX_SWIPE_UP);
+        }
     }
 
     class FallbackActivityControllerHelper implements ActivityControlHelper<RecentsActivity> {
 
+        private final ComponentName mHomeComponent;
+        private final Handler mUiHandler = new Handler(Looper.getMainLooper());
+
+        public FallbackActivityControllerHelper(ComponentName homeComponent) {
+            mHomeComponent = homeComponent;
+        }
+
         @Override
-        public boolean onQuickInteractionStart(RecentsActivity activity, boolean activityVisible) {
-            // Activity does not need any UI change for quickscrub.
-            return false;
+        public void onQuickInteractionStart(RecentsActivity activity, RunningTaskInfo taskInfo,
+                boolean activityVisible) {
+            QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
+                    .getQuickScrubController();
+
+            // TODO: match user is as well
+            boolean startingFromHome = !activityVisible &&
+                    (taskInfo == null || Objects.equals(taskInfo.topActivity, mHomeComponent));
+            controller.onQuickScrubStart(startingFromHome, this);
+            if (activityVisible) {
+                mUiHandler.postDelayed(controller::onFinishedTransitionToQuickScrub,
+                        OVERVIEW_TRANSITION_MS);
+            }
         }
 
         @Override
@@ -451,6 +489,12 @@
                 RemoteAnimationTargetSet targetSet) {
             return null;
         }
+
+        @Override
+        public AlphaProperty getAlphaProperty(RecentsActivity activity) {
+            return activity.getDragLayer().getAlphaProperty(0);
+        }
+
     }
 
     interface LayoutListener {
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 3ec2d23..2028501 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -56,7 +56,6 @@
 import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper;
 import com.android.quickstep.util.ClipAnimationHelper;
 import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.quickstep.util.SysuiEventLogger;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.LatencyTrackerCompat;
@@ -138,7 +137,7 @@
         } else {
             // The default home app is a different launcher. Use the fallback Overview instead.
             overviewComponent = new ComponentName(mContext, RecentsActivity.class);
-            mActivityControlHelper = new FallbackActivityControllerHelper();
+            mActivityControlHelper = new FallbackActivityControllerHelper(defaultHome);
             overviewIntentCategory = Intent.CATEGORY_DEFAULT;
 
             // User's default home app can change as a result of package updates of this app (such
@@ -229,10 +228,7 @@
 
             if (!handleCommand(elapsedTime)) {
                 // Start overview
-                if (mHelper.switchToRecentsIfVisible()) {
-                    SysuiEventLogger.writeDummyRecentsTransition(0);
-                    // Do nothing
-                } else {
+                if (!mHelper.switchToRecentsIfVisible()) {
                     mListener = mHelper.createActivityInitListener(this::onActivityReady);
                     mListener.registerAndStartActivity(overviewIntent, this::createWindowAnimation,
                             mContext, mMainThreadExecutor.getHandler(), RECENTS_LAUNCH_DURATION);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 3babd1f..7496b47 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -350,8 +350,7 @@
 
                 mStartPending = true;
                 Runnable action = () -> {
-                    mQuickScrubController.onQuickScrubStart(mActivityHelper.onQuickInteractionStart(
-                            mActivity, true), mActivityHelper);
+                    mActivityHelper.onQuickInteractionStart(mActivity, null, true);
                     mQuickScrubController.onQuickScrubProgress(mLastProgress);
                     mStartPending = false;
 
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 57993a4..f29cc22 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -26,6 +26,7 @@
 import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.annotation.TargetApi;
 import android.app.ActivityManager.RunningTaskInfo;
@@ -58,6 +59,8 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
 import com.android.quickstep.ActivityControlHelper.AnimationFactory;
@@ -65,7 +68,6 @@
 import com.android.quickstep.TouchConsumer.InteractionType;
 import com.android.quickstep.util.ClipAnimationHelper;
 import com.android.quickstep.util.RemoteAnimationTargetSet;
-import com.android.quickstep.util.SysuiEventLogger;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -168,6 +170,7 @@
     private final ActivityInitListener mActivityInitListener;
 
     private final int mRunningTaskId;
+    private final RunningTaskInfo mRunningTaskInfo;
     private ThumbnailData mTaskSnapshot;
 
     private MultiStateCallback mStateCallback;
@@ -204,6 +207,7 @@
     WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs,
             ActivityControlHelper<T> controller) {
         mContext = context;
+        mRunningTaskInfo = runningTaskInfo;
         mRunningTaskId = runningTaskInfo.id;
         mTouchTimeMs = touchTimeMs;
         mActivityControlHelper = controller;
@@ -368,15 +372,15 @@
             mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
         } else {
             TraceHelper.beginSection("WTS-init");
-            View rootView = activity.getRootView();
-            rootView.setAlpha(0);
-            rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
+            View dragLayer = activity.getDragLayer();
+            mActivityControlHelper.getAlphaProperty(activity).setValue(0);
+            dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
 
                 @Override
                 public void onDraw() {
                     TraceHelper.endSection("WTS-init", "Launcher frame is drawn");
-                    rootView.post(() ->
-                            rootView.getViewTreeObserver().removeOnDrawListener(this));
+                    dragLayer.post(() ->
+                            dragLayer.getViewTreeObserver().removeOnDrawListener(this));
                     if (activity != mActivity) {
                         return;
                     }
@@ -398,15 +402,22 @@
     }
 
     private void launcherFrameDrawn() {
-        View rootView = mActivity.getRootView();
-        if (rootView.getAlpha() < 1) {
+        AlphaProperty property = mActivityControlHelper.getAlphaProperty(mActivity);
+        if (property.getValue() < 1) {
             if (mGestureStarted) {
                 final MultiStateCallback callback = mStateCallback;
-                rootView.animate().alpha(1)
-                        .setDuration(getFadeInDuration())
-                        .withEndAction(() -> callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE));
+                ObjectAnimator animator = ObjectAnimator.ofFloat(
+                        property, MultiValueAlpha.VALUE, 1);
+                animator.setDuration(getFadeInDuration()).addListener(
+                        new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE);
+                            }
+                        });
+                animator.start();
             } else {
-                rootView.setAlpha(1);
+                property.setValue(1);
                 mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE);
             }
         }
@@ -425,8 +436,6 @@
         buildAnimationController();
 
         final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs;
-        SysuiEventLogger.writeDummyRecentsTransition(transitionDelay);
-
         if (LatencyTrackerCompat.isEnabled(mContext)) {
             LatencyTrackerCompat.logToggleRecents((int) transitionDelay);
         }
@@ -682,6 +691,7 @@
     private void invalidateHandlerWithLauncher() {
         mLauncherTransitionController = null;
         mLayoutListener.finish();
+        mActivityControlHelper.getAlphaProperty(mActivity).setValue(1);
 
         mRecentsView.setRunningTaskHidden(false);
         mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
@@ -761,8 +771,7 @@
             mLauncherTransitionController = null;
         }
 
-        mActivityControlHelper.onQuickInteractionStart(mActivity, false);
-        mQuickScrubController.onQuickScrubStart(false, mActivityControlHelper);
+        mActivityControlHelper.onQuickInteractionStart(mActivity, mRunningTaskInfo, false);
 
         // Inform the last progress in case we skipped before.
         mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index fb4aa02..9e2de33 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -35,6 +35,7 @@
     public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         setOverviewStateEnabled(true);
+        getQuickScrubController().onFinishedTransitionToQuickScrub();
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
index 878a593..ca8c252 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java
@@ -35,7 +35,7 @@
     private final Point mLastKnownSize = new Point(10, 10);
 
     public RecentsRootView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        super(context, attrs, 1 /* alphaChannelCount */);
         mActivity = (RecentsActivity) BaseActivity.fromContext(context);
         setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                 | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
diff --git a/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java b/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java
deleted file mode 100644
index d474ded..0000000
--- a/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 android.metrics.LogMaker;
-import android.util.EventLog;
-
-/**
- * Utility class for writing logs on behalf of systemUI
- */
-public class SysuiEventLogger {
-
-    /** 524292 sysui_multi_action (content|4) */
-    public static final int SYSUI_MULTI_ACTION = 524292;
-
-    private static void write(LogMaker content) {
-        if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) {
-            content.setType(4/*MetricsEvent.TYPE_ACTION*/);
-        }
-        EventLog.writeEvent(SYSUI_MULTI_ACTION, content.serialize());
-    }
-
-    public static void writeDummyRecentsTransition(long transitionDelay) {
-        // Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for
-        // "Recents" activity for app transition tests for the app-to-recents case.
-        final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/);
-        builder.setPackageName("com.android.systemui");
-        builder.addTaggedData(871/*FIELD_CLASS_NAME*/,
-                "com.android.systemui.recents.RecentsActivity");
-        builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/,
-                transitionDelay);
-        write(builder);
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index e237500..950f7fb 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -148,6 +148,9 @@
     protected void onTaskLaunched(boolean success) {
         if (success) {
             mActivity.getStateManager().goToState(NORMAL, false /* animate */);
+        } else {
+            LauncherState state = mActivity.getStateManager().getState();
+            mActivity.getAllAppsController().setProgress(state.getVerticalProgress(mActivity));
         }
         super.onTaskLaunched(success);
     }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5035721..a8e38a1 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -22,6 +22,7 @@
 import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -106,6 +107,8 @@
     };
     public static final boolean FLIP_RECENTS = true;
     private static final int DISMISS_TASK_DURATION = 300;
+    // The threshold at which we update the SystemUI flags when animating from the task into the app
+    private static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.6f;
 
     private static final float[] sTempFloatArray = new float[3];
 
@@ -1152,12 +1155,21 @@
         }
 
         tv.setVisibility(INVISIBLE);
+        int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
         TaskViewDrawable drawable = new TaskViewDrawable(tv, this);
         getOverlay().add(drawable);
 
         ObjectAnimator drawableAnim =
                 ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
         drawableAnim.setInterpolator(LINEAR);
+        drawableAnim.addUpdateListener((animator) -> {
+            // Once we pass a certain threshold, update the sysui flags to match the target tasks'
+            // flags
+            mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW,
+                    animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD
+                            ? targetSysUiFlags
+                            : 0);
+        });
 
         AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv,
                 drawable.getClipAnimationHelper());
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
index a951de9..429432b 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
@@ -75,8 +75,8 @@
     }
 
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
 
         mRecentsView.getTaskSize(mTempRect);
 
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index c724930..af7a735 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -16,6 +16,7 @@
 
 package com.android.quickstep.views;
 
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
 
 import android.content.Context;
@@ -38,6 +39,7 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.SystemUiController;
 import com.android.quickstep.TaskOverlayFactory;
 import com.android.quickstep.TaskOverlayFactory.TaskOverlay;
 import com.android.systemui.shared.recents.model.Task;
@@ -143,6 +145,20 @@
         return new Rect();
     }
 
+    public int getSysUiStatusNavFlags() {
+        if (mThumbnailData != null) {
+            int flags = 0;
+            flags |= (mThumbnailData.systemUiVisibility & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
+                    ? SystemUiController.FLAG_LIGHT_STATUS
+                    : SystemUiController.FLAG_DARK_STATUS;
+            flags |= (mThumbnailData.systemUiVisibility & SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
+                    ? SystemUiController.FLAG_LIGHT_NAV
+                    : SystemUiController.FLAG_DARK_NAV;
+            return flags;
+        }
+        return 0;
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius);
@@ -154,21 +170,24 @@
 
     public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
             float cornerRadius) {
-        // Always draw the background since the snapshots may be translucent
-        canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint);
-        if (mTask == null) {
-            return;
-        }
-        if (!mTask.isLocked) {
-            if (mClipBottom > 0) {
-                canvas.save();
-                canvas.clipRect(x, y, width, mClipBottom);
-                canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
-                canvas.restore();
-            } else {
-                canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
+        // Draw the background in all cases, except when the thumbnail data is opaque
+        final boolean drawBackgroundOnly = mTask == null || mTask.isLocked || mBitmapShader == null
+                || mThumbnailData == null;
+        if (drawBackgroundOnly || mClipBottom > 0 || mThumbnailData.isTranslucent) {
+            canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint);
+            if (drawBackgroundOnly) {
+                return;
             }
         }
+
+        if (mClipBottom > 0) {
+            canvas.save();
+            canvas.clipRect(x, y, width, mClipBottom);
+            canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
+            canvas.restore();
+        } else {
+            canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint);
+        }
     }
 
     private void updateThumbnailPaintFilter() {
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index bd38bf0..1f70cfa 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.app.Activity;
@@ -153,6 +154,12 @@
     protected void onPause() {
         mActivityFlags &= ~ACTIVITY_STATE_RESUMED;
         super.onPause();
+
+        // Reset the overridden sysui flags used for the task-swipe launch animation, we do this
+        // here instead of at the end of the animation because the start of the new activity does
+        // not happen immediately, which would cause us to reset to launcher's sysui flags and then
+        // back to the new app (causing a flash)
+        getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
     }
 
     public boolean isStarted() {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index b45ee2d..12d29a8 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -22,10 +22,13 @@
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
 import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.TargetApi;
 import android.app.ActivityOptions;
@@ -103,6 +106,8 @@
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.MultiHashMap;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.PendingRequestArgs;
@@ -308,7 +313,7 @@
             if (!internalStateHandled) {
                 // If we are not binding synchronously, show a fade in animation when
                 // the first page bind completes.
-                mLauncherView.setAlpha(0);
+                mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
             }
         } else {
             // Pages bound synchronously.
@@ -2086,9 +2091,18 @@
 
     @Override
     public void finishFirstPageBind(final ViewOnDrawExecutor executor) {
-        if (mLauncherView.getAlpha() < 1) {
-            mLauncherView.animate().alpha(1).withEndAction(
-                    executor == null ? null : executor::onLoadAnimationCompleted).start();
+        AlphaProperty property = mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD);
+        if (property.getValue() < 1) {
+            ObjectAnimator anim = ObjectAnimator.ofFloat(property, MultiValueAlpha.VALUE, 1);
+            if (executor != null) {
+                anim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        executor.onLoadAnimationCompleted();
+                    }
+                });
+            }
+            anim.start();
         } else if (executor != null) {
             executor.onLoadAnimationCompleted();
         }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 223fa97..a03a7a8 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -22,6 +22,7 @@
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
+import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -1174,7 +1175,7 @@
         // different effects based on device performance. On at least one relatively high-end
         // device I've tried, translating the launcher causes things to get quite laggy.
         mLauncher.getDragLayer().setTranslationX(transX);
-        mLauncher.getDragLayer().setAlpha(alpha);
+        mLauncher.getDragLayer().getAlphaProperty(ALPHA_INDEX_OVERLAY).setValue(alpha);
     }
 
     /**
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index aad1e5a..3a1837d 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -62,6 +62,12 @@
  */
 public class DragLayer extends BaseDragLayer<Launcher> {
 
+    public static final int ALPHA_INDEX_OVERLAY = 0;
+    public static final int ALPHA_INDEX_LAUNCHER_LOAD = 1;
+    public static final int ALPHA_INDEX_TRANSITIONS = 2;
+    public static final int ALPHA_INDEX_SWIPE_UP = 3;
+    private static final int ALPHA_CHANNEL_COUNT = 4;
+
     public static final int ANIMATION_END_DISAPPEAR = 0;
     public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
 
@@ -90,7 +96,7 @@
      * @param attrs The attributes set containing the Workspace's customization values.
      */
     public DragLayer(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        super(context, attrs, ALPHA_CHANNEL_COUNT);
 
         // Disable multitouch across the workspace/all apps/customize tray
         setMotionEventSplittingEnabled(false);
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
new file mode 100644
index 0000000..f810f48
--- /dev/null
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -0,0 +1,101 @@
+/*
+ * 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.launcher3.util;
+
+import android.util.Property;
+import android.view.View;
+
+/**
+ * Utility class to handle separating a single value as a factor of multiple values
+ */
+public class MultiValueAlpha {
+
+    public static final Property<AlphaProperty, Float> VALUE =
+            new Property<AlphaProperty, Float>(Float.TYPE, "value") {
+
+                @Override
+                public Float get(AlphaProperty alphaProperty) {
+                    return alphaProperty.mValue;
+                }
+
+                @Override
+                public void set(AlphaProperty object, Float value) {
+                    object.setValue(value);
+                }
+            };
+
+    private final View mView;
+    private final AlphaProperty[] mMyProperties;
+
+    private int mValidMask;
+
+    public MultiValueAlpha(View view, int size) {
+        mView = view;
+        mMyProperties = new AlphaProperty[size];
+
+        mValidMask = 0;
+        for (int i = 0; i < size; i++) {
+            int myMask = 1 << i;
+            mValidMask |= myMask;
+            mMyProperties[i] = new AlphaProperty(myMask);
+        }
+    }
+
+    public AlphaProperty getProperty(int index) {
+        return mMyProperties[index];
+    }
+
+    public class AlphaProperty {
+
+        private final int mMyMask;
+
+        private float mValue = 1;
+        // Factor of all other alpha channels, only valid if mMyMask is present in mValidMask.
+        private float mOthers = 1;
+
+        AlphaProperty(int myMask) {
+            mMyMask = myMask;
+        }
+
+        public void setValue(float value) {
+            if (mValue == value) {
+                return;
+            }
+
+            if ((mValidMask & mMyMask) == 0) {
+                // Our cache value is not correct, recompute it.
+                mOthers = 1;
+                for (AlphaProperty prop : mMyProperties) {
+                    if (prop != this) {
+                        mOthers *= prop.mValue;
+                    }
+                }
+            }
+
+            // Since we have changed our value, all other caches except our own need to be
+            // recomputed. Change mValidMask to indicate the new valid caches (only our own).
+            mValidMask = mMyMask;
+            mValue = value;
+
+            mView.setAlpha(mOthers * mValue);
+        }
+
+        public float getValue() {
+            return mValue;
+        }
+    }
+}
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index edbf05a..7ef53a9 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -31,6 +31,7 @@
     public static final int UI_STATE_ALL_APPS = 1;
     public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
     public static final int UI_STATE_ROOT_VIEW = 3;
+    public static final int UI_STATE_OVERVIEW = 4;
 
     public static final int FLAG_LIGHT_NAV = 1 << 0;
     public static final int FLAG_DARK_NAV = 1 << 1;
@@ -38,7 +39,7 @@
     public static final int FLAG_DARK_STATUS = 1 << 3;
 
     private final Window mWindow;
-    private final int[] mStates = new int[4];
+    private final int[] mStates = new int[5];
 
     public SystemUiController(Window window) {
         mWindow = window;
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 149b38b..66d9498 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -30,6 +30,8 @@
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.launcher3.util.TouchController;
 
 import java.util.ArrayList;
@@ -45,17 +47,18 @@
     protected final Rect mHitRect = new Rect();
 
     protected final T mActivity;
+    private final MultiValueAlpha mMultiValueAlpha;
 
     protected TouchController[] mControllers;
     protected TouchController mActiveController;
     private TouchCompleteListener mTouchCompleteListener;
 
-    public BaseDragLayer(Context context, AttributeSet attrs) {
+    public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
         super(context, attrs);
         mActivity = (T) BaseActivity.fromContext(context);
+        mMultiValueAlpha = new MultiValueAlpha(this, alphaChannelCount);
     }
 
-
     public boolean isEventOverView(View view, MotionEvent ev) {
         getDescendantRectRelativeToSelf(view, mHitRect);
         return mHitRect.contains((int) ev.getX(), (int) ev.getY());
@@ -276,6 +279,10 @@
         return new LayoutParams(p);
     }
 
+    public AlphaProperty getAlphaProperty(int index) {
+        return mMultiValueAlpha.getProperty(index);
+    }
+
     public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
         public int x, y;
         public boolean customPosition = false;
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 56b92c7..c17857f 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -184,6 +184,7 @@
         Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER)
                 .putExtra(EXTRA_WALLPAPER_OFFSET,
                         launcher.getWorkspace().getWallpaperOffsetForCenterPage());
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
 
         String pickerPackage = launcher.getString(R.string.wallpaper_picker_package);
         if (!TextUtils.isEmpty(pickerPackage)) {