Merge "Test: using RuleChain to create a correct order of rules." into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index a6c4445..d66af1a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -98,9 +98,6 @@
         if (mStartState == OVERVIEW || mStartState == ALL_APPS) {
             return true;
         }
-        if (!mLauncher.hasWindowFocus()) {
-            return true;
-        }
         if (AbstractFloatingView.getTopOpenView(mLauncher) != null) {
             return true;
         }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index cbc94ba..dc35440 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -62,6 +62,7 @@
 
 import androidx.annotation.BinderThread;
 
+import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.R;
 import com.android.launcher3.ResourceUtils;
@@ -79,6 +80,7 @@
 import com.android.quickstep.inputconsumers.InputConsumer;
 import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
+import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
 import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -566,10 +568,9 @@
             info.id = mSwipeSharedState.nextRunningTaskId;
             return createOtherActivityInputConsumer(event, info);
         } else if (mSwipeSharedState.goingToLauncher || activityControl.isResumed()) {
-            return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false);
-        } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
-                activityControl.isInLiveTileMode()) {
-            return OverviewInputConsumer.newInstance(activityControl, mInputMonitorCompat, false);
+            return createOverviewInputConsumer(event);
+        } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) {
+            return createOverviewInputConsumer(event);
         } else if (mGestureBlockingActivity != null && runningTaskInfo != null
                 && mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
             return InputConsumer.NO_OP;
@@ -578,20 +579,24 @@
         }
     }
 
+    private boolean disableHorizontalSwipe(MotionEvent event) {
+        // mExclusionRegion can change on binder thread, use a local instance here.
+        Region exclusionRegion = mExclusionRegion;
+        return mMode == Mode.NO_BUTTON && exclusionRegion != null
+                && exclusionRegion.contains((int) event.getX(), (int) event.getY());
+    }
+
     private OtherActivityInputConsumer createOtherActivityInputConsumer(MotionEvent event,
             RunningTaskInfo runningTaskInfo) {
         final ActivityControlHelper activityControl =
                 mOverviewComponentObserver.getActivityControlHelper();
         boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
 
-        // mExclusionRegion can change on binder thread, use a local instance here.
-        Region exclusionRegion = mExclusionRegion;
-        boolean disableHorizontalSwipe = mMode == Mode.NO_BUTTON && exclusionRegion != null
-                && exclusionRegion.contains((int) event.getX(), (int) event.getY());
         return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
                 mOverviewComponentObserver.getOverviewIntent(), activityControl,
                 shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive,
-                mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, disableHorizontalSwipe);
+                mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
+                disableHorizontalSwipe(event));
     }
 
     private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
@@ -603,6 +608,23 @@
         }
     }
 
+    public InputConsumer createOverviewInputConsumer(MotionEvent event) {
+        final ActivityControlHelper activityControl =
+                mOverviewComponentObserver.getActivityControlHelper();
+        BaseDraggingActivity activity = activityControl.getCreatedActivity();
+        if (activity == null) {
+            return InputConsumer.NO_OP;
+        }
+
+        if (activity.getRootView().hasWindowFocus()) {
+            return new OverviewInputConsumer(activity, mInputMonitorCompat,
+                    false /* startingInActivityBounds */);
+        } else {
+            return new OverviewWithoutFocusInputConsumer(this, mInputMonitorCompat,
+                    disableHorizontalSwipe(event));
+        }
+    }
+
     /**
      * To be called by the consumer when it's no longer active.
      */
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 87b7326..8b1efb2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -267,6 +267,7 @@
     private MultiStateCallback mStateCallback;
     // Used to control launcher components throughout the swipe gesture.
     private AnimatorPlaybackController mLauncherTransitionController;
+    private boolean mHasLauncherTransitionControllerStarted;
 
     private T mActivity;
     private RecentsView mRecentsView;
@@ -647,8 +648,7 @@
     }
 
     private void buildAnimationController() {
-        if (mGestureEndTarget == HOME || (mLauncherTransitionController != null
-                && mLauncherTransitionController.getAnimationPlayer().isStarted())) {
+        if (mGestureEndTarget == HOME || mHasLauncherTransitionControllerStarted) {
             // We don't want a new mLauncherTransitionController if mGestureEndTarget == HOME (it
             // has its own animation) or if we're already animating the current controller.
             return;
@@ -858,7 +858,9 @@
             setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
         }
 
-        return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true);
+        BaseDraggingActivity activity = mActivityControlHelper.getCreatedActivity();
+        return activity == null
+                ? InputConsumer.NO_OP : new OverviewInputConsumer(activity, null, true);
     }
 
     private void endRunningWindowAnim() {
@@ -1122,6 +1124,7 @@
             }
             mLauncherTransitionController.getAnimationPlayer().start();
         }
+        mHasLauncherTransitionControllerStarted = true;
     }
 
     /**
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
index 6e7cb8f..489eb27 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
@@ -31,6 +31,7 @@
     int TYPE_DEVICE_LOCKED = 1 << 4;
     int TYPE_ACCESSIBILITY = 1 << 5;
     int TYPE_SCREEN_PINNED = 1 << 6;
+    int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
 
     InputConsumer NO_OP = () -> TYPE_NO_OP;
 
@@ -78,6 +79,8 @@
                 return "ACCESSIBILITY";
             case TYPE_SCREEN_PINNED:
                 return "SCREEN_PINNED";
+            case TYPE_OVERVIEW_WITHOUT_FOCUS:
+                return "TYPE_OVERVIEW_WITHOUT_FOCUS";
             default:
                 return "NO_OP";
         }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 0ed4c99..69b25db 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -28,7 +28,6 @@
 import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
 import static com.android.launcher3.util.RaceConditionTracker.ENTER;
 import static com.android.launcher3.util.RaceConditionTracker.EXIT;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
@@ -43,10 +42,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.view.MotionEvent;
-import android.view.Surface;
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
-import android.view.WindowManager;
 
 import androidx.annotation.UiThread;
 
@@ -65,6 +62,7 @@
 import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
 import com.android.quickstep.util.CachedEventDispatcher;
 import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.util.NavBarPosition;
 import com.android.quickstep.util.RecentsAnimationListenerSet;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.BackgroundExecutor;
@@ -95,7 +93,7 @@
     private final SysUINavigationMode.Mode mMode;
     private final RectF mSwipeTouchRegion;
 
-    private final int mDisplayRotation;
+    private final NavBarPosition mNavBarPosition;
 
     private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
     private final MotionPauseDetector mMotionPauseDetector;
@@ -157,7 +155,7 @@
         mInputConsumer = inputConsumer;
         mSwipeSharedState = swipeSharedState;
 
-        mDisplayRotation = getSystemService(WindowManager.class).getDefaultDisplay().getRotation();
+        mNavBarPosition = new NavBarPosition(base);
         mDragSlop = QuickStepContract.getQuickStepDragSlopPx();
         float slop = QuickStepContract.getQuickStepTouchSlopPx();
         mSquaredTouchSlop = slop * slop;
@@ -188,9 +186,7 @@
         if (mPassedDragSlop && mInteractionHandler != null
                 && !mRecentsViewDispatcher.hasConsumer()) {
             mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
-                    isNavBarOnLeft()
-                            ? ROTATION_SEASCAPE
-                            : (isNavBarOnRight() ? ROTATION_LANDSCAPE : RotationMode.NORMAL)));
+                    mNavBarPosition.getRotationMode()));
         }
         int edgeFlags = ev.getEdgeFlags();
         ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
@@ -329,14 +325,6 @@
         mInteractionHandler.onGestureStarted();
     }
 
-    private boolean isNavBarOnRight() {
-        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
-    }
-
-    private boolean isNavBarOnLeft() {
-        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
-    }
-
     private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
         TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
 
@@ -382,8 +370,8 @@
                         ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
                 float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
                 float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
-                float velocity = isNavBarOnRight() ? velocityX
-                        : isNavBarOnLeft() ? -velocityX
+                float velocity = mNavBarPosition.isRightEdge() ? velocityX
+                        : mNavBarPosition.isLeftEdge() ? -velocityX
                                 : velocityY;
 
                 mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
@@ -444,9 +432,9 @@
     }
 
     private float getDisplacement(MotionEvent ev) {
-        if (isNavBarOnRight()) {
+        if (mNavBarPosition.isRightEdge()) {
             return ev.getX() - mDownPos.x;
-        } else if (isNavBarOnLeft()) {
+        } else if (mNavBarPosition.isLeftEdge()) {
             return mDownPos.x - ev.getX();
         } else {
             return ev.getY() - mDownPos.y;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index bab3c71..4851e67 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -51,7 +51,7 @@
     private final boolean mStartingInActivityBounds;
     private boolean mTargetHandledTouch;
 
-    OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor,
+    public OverviewInputConsumer(T activity, @Nullable InputMonitorCompat inputMonitor,
             boolean startingInActivityBounds) {
         mActivity = activity;
         mInputMonitor = inputMonitor;
@@ -115,12 +115,12 @@
         }
     }
 
-    public static InputConsumer newInstance(ActivityControlHelper activityHelper,
-            @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) {
+    public static InputConsumer newInstanceWithinActivityBounds(
+            ActivityControlHelper activityHelper) {
         BaseDraggingActivity activity = activityHelper.getCreatedActivity();
         if (activity == null) {
             return InputConsumer.NO_OP;
         }
-        return new OverviewInputConsumer(activity, inputMonitor, startingInActivityBounds);
+        return new OverviewInputConsumer(activity, null, true);
     }
 }
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
new file mode 100644
index 0000000..425b8b6
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2019 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.inputconsumers;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import static com.android.launcher3.Utilities.squaredHypot;
+import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
+import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+
+import com.android.launcher3.Utilities;
+import com.android.quickstep.OverviewCallbacks;
+import com.android.quickstep.util.NavBarPosition;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+public class OverviewWithoutFocusInputConsumer implements InputConsumer {
+
+    private final InputMonitorCompat mInputMonitor;
+    private final boolean mDisableHorizontalSwipe;
+    private final PointF mDownPos = new PointF();
+    private final float mSquaredTouchSlop;
+    private final Context mContext;
+    private final NavBarPosition mNavBarPosition;
+
+    private boolean mInterceptedTouch;
+    private VelocityTracker mVelocityTracker;
+
+
+    public OverviewWithoutFocusInputConsumer(Context context, InputMonitorCompat inputMonitor,
+            boolean disableHorizontalSwipe) {
+        mInputMonitor = inputMonitor;
+        mDisableHorizontalSwipe = disableHorizontalSwipe;
+        mContext = context;
+        mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
+        mNavBarPosition = new NavBarPosition(context);
+
+        mVelocityTracker = VelocityTracker.obtain();
+    }
+
+    @Override
+    public int getType() {
+        return TYPE_OVERVIEW_WITHOUT_FOCUS;
+    }
+
+    @Override
+    public boolean allowInterceptByParent() {
+        return !mInterceptedTouch;
+    }
+
+    private void endTouchTracking() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent ev) {
+        if (mVelocityTracker == null) {
+            return;
+        }
+
+        mVelocityTracker.addMovement(ev);
+        switch (ev.getActionMasked()) {
+            case ACTION_DOWN: {
+                mDownPos.set(ev.getX(), ev.getY());
+                break;
+            }
+            case ACTION_MOVE: {
+                if (!mInterceptedTouch) {
+                    float displacementX = ev.getX() - mDownPos.x;
+                    float displacementY = ev.getY() - mDownPos.y;
+                    if (squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop) {
+                        if (mDisableHorizontalSwipe
+                                && Math.abs(displacementX) > Math.abs(displacementY)) {
+                            // Horizontal gesture is not allowed in this region
+                            endTouchTracking();
+                            break;
+                        }
+
+                        mInterceptedTouch = true;
+
+                        if (mInputMonitor != null) {
+                            mInputMonitor.pilferPointers();
+                        }
+                    }
+                }
+                break;
+            }
+
+            case ACTION_CANCEL:
+                endTouchTracking();
+                break;
+
+            case ACTION_UP: {
+                finishTouchTracking(ev);
+                endTouchTracking();
+                break;
+            }
+        }
+    }
+
+    private void finishTouchTracking(MotionEvent ev) {
+        mVelocityTracker.computeCurrentVelocity(100);
+        float velocityX = mVelocityTracker.getXVelocity();
+        float velocityY = mVelocityTracker.getYVelocity();
+        float velocity = mNavBarPosition.isRightEdge()
+                ? -velocityX : (mNavBarPosition.isLeftEdge() ? velocityX : -velocityY);
+
+        final boolean triggerQuickstep;
+        if (Math.abs(velocity) >= ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity()) {
+            triggerQuickstep = velocity > 0;
+        } else {
+            float displacementX = mDisableHorizontalSwipe ? 0 : (ev.getX() - mDownPos.x);
+            float displacementY = ev.getY() - mDownPos.y;
+            triggerQuickstep = squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop;
+        }
+
+        if (triggerQuickstep) {
+            OverviewCallbacks.get(mContext).closeAllWindows();
+            ActivityManagerWrapper.getInstance()
+                    .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
+            TOUCH_INTERACTION_LOG.addLog("startQuickstep");
+        } else {
+            // ignore
+        }
+    }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
new file mode 100644
index 0000000..3ce341d
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/NavBarPosition.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 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.launcher3.uioverrides.RecentsUiFactory.ROTATION_LANDSCAPE;
+import static com.android.launcher3.uioverrides.RecentsUiFactory.ROTATION_SEASCAPE;
+import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+
+import android.content.Context;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import com.android.launcher3.graphics.RotationMode;
+import com.android.quickstep.SysUINavigationMode;
+
+/**
+ * Utility class to check nav bar position
+ */
+public class NavBarPosition {
+
+    private final SysUINavigationMode.Mode mMode;
+    private final int mDisplayRotation;
+
+    public NavBarPosition(Context context) {
+        mMode = SysUINavigationMode.getMode(context);
+        mDisplayRotation = context.getSystemService(WindowManager.class)
+                .getDefaultDisplay().getRotation();
+    }
+
+    public boolean isRightEdge() {
+        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
+    }
+
+    public boolean isLeftEdge() {
+        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
+    }
+
+    public RotationMode getRotationMode() {
+        return isLeftEdge() ? ROTATION_SEASCAPE
+                : (isRightEdge() ? ROTATION_LANDSCAPE : RotationMode.NORMAL);
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index dcf2e3c..46161cb 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -108,7 +108,7 @@
     // Use a shorter duration for x or y translation to create a curve effect
     private static final long APP_LAUNCH_CURVED_DURATION = 250;
     private static final long APP_LAUNCH_ALPHA_DURATION = 50;
-    private static final long APP_LAUNCH_ALPHA_START_DELAY = 50;
+    private static final long APP_LAUNCH_ALPHA_START_DELAY = 25;
 
     // We scale the durations for the downward app launch animations (minus the scale animation).
     private static final float APP_LAUNCH_DOWN_DUR_SCALE_FACTOR = 0.8f;