Merge "Send onGestureStarted() when continuing a quick switch gesture" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java
index 963f1fa..fdb80da 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/BackgroundAppState.java
@@ -20,6 +20,7 @@
 import android.os.RemoteException;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
@@ -72,4 +73,13 @@
         float scale = (float) appWidth / sTempRect.width();
         return new float[] { scale, 0f };
     }
+
+    @Override
+    public int getVisibleElements(Launcher launcher) {
+        if (FeatureFlags.SWIPE_HOME.get()) {
+            return super.getVisibleElements(launcher);
+        }
+        // Hide shelf content (e.g. QSB) because we fade it in when swiping up.
+        return ALL_APPS_HEADER_EXTRA;
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index 971987a..eee0344 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -23,6 +23,7 @@
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO;
 import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 
 import android.animation.Animator;
@@ -38,13 +39,20 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherInitListener;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.AnimatorSetBuilder;
 import com.android.launcher3.anim.SpringObjectAnimator;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.config.FeatureFlags;
@@ -61,10 +69,6 @@
 import java.util.function.BiPredicate;
 import java.util.function.Consumer;
 
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-
 /**
  * {@link ActivityControlHelper} for the in-launcher recents.
  */
@@ -212,7 +216,7 @@
                         : mShelfState == ShelfAnimState.PEEK
                                 ? shelfPeekingProgress
                                 : shelfOverviewProgress;
-                mShelfAnim = createShelfAnim(activity, toProgress);
+                mShelfAnim = createShelfProgressAnim(activity, toProgress);
                 mShelfAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
@@ -230,10 +234,10 @@
             LauncherState fromState, long transitionLength,
             Consumer<AnimatorPlaybackController> callback) {
         LauncherState endState = OVERVIEW;
+        DeviceProfile dp = activity.getDeviceProfile();
+        long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
         if (wasVisible && fromState != BACKGROUND_APP) {
             // If a translucent app was launched fom launcher, animate launcher states.
-            DeviceProfile dp = activity.getDeviceProfile();
-            long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
             callback.accept(activity.getStateManager()
                     .createAnimationToNewWorkspace(fromState, endState, accuracy));
             return;
@@ -246,10 +250,11 @@
         if (!activity.getDeviceProfile().isVerticalBarLayout()
                 && !FeatureFlags.SWIPE_HOME.get()) {
             // Don't animate the shelf when SWIPE_HOME is true, because we update it atomically.
-            Animator shiftAnim = createShelfAnim(activity,
+            Animator shiftAnim = createShelfProgressAnim(activity,
                     fromState.getVerticalProgress(activity),
                     endState.getVerticalProgress(activity));
             anim.play(shiftAnim);
+            anim.play(createShelfAlphaAnim(activity, endState, accuracy));
         }
         playScaleDownAnim(anim, activity, endState);
 
@@ -266,7 +271,7 @@
         callback.accept(controller);
     }
 
-    private Animator createShelfAnim(Launcher activity, float ... progressValues) {
+    private Animator createShelfProgressAnim(Launcher activity, float ... progressValues) {
         Animator shiftAnim = new SpringObjectAnimator<>(activity.getAllAppsController(),
                 "allAppsSpringFromACH", activity.getAllAppsController().getShiftRange(),
                 SPRING_DAMPING_RATIO, SPRING_STIFFNESS, progressValues);
@@ -275,6 +280,19 @@
     }
 
     /**
+     * Very quickly fade the alpha of shelf content.
+     */
+    private Animator createShelfAlphaAnim(Launcher activity, LauncherState toState, long accuracy) {
+        AllAppsTransitionController allAppsController = activity.getAllAppsController();
+        AnimatorSetBuilder animBuilder = new AnimatorSetBuilder();
+        animBuilder.setInterpolator(AnimatorSetBuilder.ANIM_ALL_APPS_FADE, DEACCEL_3);
+        LauncherStateManager.AnimationConfig config = new LauncherStateManager.AnimationConfig();
+        config.duration = accuracy;
+        allAppsController.setAlphas(toState.getVisibleElements(activity), config, animBuilder);
+        return animBuilder.build();
+    }
+
+    /**
      * Scale down recents from the center task being full screen to being in overview.
      */
     private void playScaleDownAnim(AnimatorSet anim, Launcher launcher,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 0aa1beb..19e9cb4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.AppUsageLimit;
 import android.content.res.Resources;
 import android.icu.text.MeasureFormat;
 import android.icu.text.MeasureFormat.FormatWidth;
@@ -44,13 +45,13 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.systemui.shared.recents.model.Task;
 
-import java.lang.reflect.Method;
 import java.time.Duration;
 import java.util.Locale;
 
 public final class DigitalWellBeingToast extends LinearLayout {
     static final Intent OPEN_APP_USAGE_SETTINGS_TEMPLATE = new Intent(ACTION_APP_USAGE_SETTINGS);
     static final int MINUTE_MS = 60000;
+    private final LauncherApps mLauncherApps;
 
     public interface InitializeCallback {
         void call(float saturation, String contentDescription);
@@ -67,6 +68,7 @@
         setLayoutDirection(Utilities.isRtl(getResources()) ?
                 View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
         setOnClickListener((view) -> openAppUsageSettings());
+        mLauncherApps = context.getSystemService(LauncherApps.class);
     }
 
     @Override
@@ -87,47 +89,29 @@
         }
 
         Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
-            long appUsageLimitTimeMs = -1;
-            long appRemainingTimeMs = -1;
+            final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
+                    task.getTopComponent().getPackageName(),
+                    UserHandle.of(task.key.userId));
 
-            try {
-                final Method getAppUsageLimit = LauncherApps.class.getMethod(
-                        "getAppUsageLimit",
-                        String.class,
-                        UserHandle.class);
-                final Object usageLimit = getAppUsageLimit.invoke(
-                        getContext().getSystemService(LauncherApps.class),
-                        task.getTopComponent().getPackageName(),
-                        UserHandle.of(task.key.userId));
-
-                if (usageLimit != null) {
-                    final Class appUsageLimitClass = usageLimit.getClass();
-                    appUsageLimitTimeMs = (long) appUsageLimitClass.getMethod("getTotalUsageLimit").
-                            invoke(usageLimit);
-                    appRemainingTimeMs = (long) appUsageLimitClass.getMethod("getUsageRemaining").
-                            invoke(usageLimit);
-                }
-            } catch (Exception e) {
-                // Do nothing
-            }
-
-            final long appUsageLimitTimeMsFinal = appUsageLimitTimeMs;
-            final long appRemainingTimeMsFinal = appRemainingTimeMs;
+            final long appUsageLimitTimeMs =
+                    usageLimit != null ? usageLimit.getTotalUsageLimit() : -1;
+            final long appRemainingTimeMs =
+                    usageLimit != null ? usageLimit.getUsageRemaining() : -1;
 
             post(() -> {
-                if (appUsageLimitTimeMsFinal < 0) {
+                if (appUsageLimitTimeMs < 0) {
                     setVisibility(GONE);
                 } else {
                     setVisibility(VISIBLE);
-                    mText.setText(getText(appRemainingTimeMsFinal));
-                    mImage.setImageResource(appRemainingTimeMsFinal > 0 ?
+                    mText.setText(getText(appRemainingTimeMs));
+                    mImage.setImageResource(appRemainingTimeMs > 0 ?
                             R.drawable.hourglass_top : R.drawable.hourglass_bottom);
                 }
 
                 callback.call(
-                        appUsageLimitTimeMsFinal >= 0 && appRemainingTimeMsFinal <= 0 ? 0 : 1,
+                        appUsageLimitTimeMs >= 0 && appRemainingTimeMs <= 0 ? 0 : 1,
                         getContentDescriptionForTask(
-                                task, appUsageLimitTimeMsFinal, appRemainingTimeMsFinal));
+                                task, appUsageLimitTimeMs, appRemainingTimeMs));
             });
         });
     }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 3b054c2..7919d29 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -133,6 +133,7 @@
     private final Rect mInsets = new Rect();
     public final Rect workspacePadding = new Rect();
     private final Rect mHotseatPadding = new Rect();
+    // When true, nav bar is on the left side of the screen.
     private boolean mIsSeascape;
 
     // Notification dots
@@ -587,28 +588,40 @@
     /**
      * Gets an item's location on the home screen. This is useful if the home screen
      * is animating, otherwise use {@link View#getLocationOnScreen(int[])}.
-     *
-     * TODO(b/123900446): Handle landscape mode
      * @param pageDiff The page difference relative to the current page.
      */
     public void getItemLocation(int cellX, int cellY, int spanX, int spanY, int container,
             int pageDiff, Rect outBounds) {
         outBounds.setEmpty();
-        outBounds.left = mInsets.left
-                + workspacePadding.left + cellLayoutPaddingLeftRightPx + (cellX * getCellSize().x);
-        outBounds.top = mInsets.top;
         if (container == CONTAINER_HOTSEAT) {
-            outBounds.top += workspacePadding.top
-                    + (inv.numRows * getCellSize().y)
-                    + verticalDragHandleSizePx
-                    - verticalDragHandleOverlapWorkspace;
-            outBounds.bottom = outBounds.top + hotseatBarSizePx - hotseatBarBottomPaddingPx;
+            final int actualHotseatCellHeight;
+            if (isVerticalBarLayout()) {
+                actualHotseatCellHeight = availableHeightPx / inv.numRows;
+                if (mIsSeascape) {
+                    outBounds.left = mHotseatPadding.left;
+                } else {
+                    outBounds.left = availableWidthPx - hotseatBarSizePx + mHotseatPadding.left;
+                }
+                outBounds.right = outBounds.left + iconSizePx;
+                outBounds.top = mHotseatPadding.top
+                        + actualHotseatCellHeight * (inv.numRows - cellX - 1);
+                outBounds.bottom = outBounds.top + actualHotseatCellHeight;
+            } else {
+                actualHotseatCellHeight = hotseatBarSizePx - hotseatBarBottomPaddingPx
+                        - hotseatBarTopPaddingPx;
+                outBounds.left = mInsets.left + workspacePadding.left + cellLayoutPaddingLeftRightPx
+                        + (cellX * getCellSize().x);
+                outBounds.right = outBounds.left + getCellSize().x;
+                outBounds.top = mInsets.top + availableHeightPx - hotseatBarSizePx;
+                outBounds.bottom = outBounds.top + actualHotseatCellHeight;
+            }
         } else {
-            outBounds.top += workspacePadding.top + (cellY * getCellSize().y);
+            outBounds.left = mInsets.left + workspacePadding.left + cellLayoutPaddingLeftRightPx
+                    + (cellX * getCellSize().x) + (pageDiff * availableWidthPx);
+            outBounds.right = outBounds.left + (getCellSize().x * spanX);
+            outBounds.top = mInsets.top + workspacePadding.top + (cellY * getCellSize().y);
             outBounds.bottom = outBounds.top + (getCellSize().y * spanY);
-            outBounds.left += (pageDiff) * availableWidthPx;
         }
-        outBounds.right = outBounds.left + (getCellSize().x * spanX);
     }
 
     public float getAspectRatioWithInsets() {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 93bf69d..a4ecec7 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -188,9 +188,12 @@
 
     private void setAlphas(LauncherState toState, AnimationConfig config,
             AnimatorSetBuilder builder) {
+        setAlphas(toState.getVisibleElements(mLauncher), config, builder);
+    }
+
+    public void setAlphas(int visibleElements, AnimationConfig config, AnimatorSetBuilder builder) {
         PropertySetter setter = config == null ? NO_ANIM_PROPERTY_SETTER
                 : config.getPropertySetter(builder);
-        int visibleElements = toState.getVisibleElements(mLauncher);
         boolean hasHeaderExtra = (visibleElements & ALL_APPS_HEADER_EXTRA) != 0;
         boolean hasContent = (visibleElements & ALL_APPS_CONTENT) != 0;