Merge "Screenshots - move to new api that uses image bundle." into ub-launcher3-rvc-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 12d537c..99cb3b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -145,11 +145,23 @@
         int rightInset = insets.right - mInsets.right;
         int bottomInset = insets.bottom - mInsets.bottom;
         mInsets.set(insets);
-        setPadding(leftInset, getPaddingTop(), rightInset, 0);
-        mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
-                mHotseatWrapper.getPaddingRight(), bottomInset);
-        mHotseatWrapper.getLayoutParams().height =
-                mLauncher.getDeviceProfile().hotseatBarSizePx + insets.bottom;
+        if (mLauncher.getOrientation() == Configuration.ORIENTATION_PORTRAIT) {
+            setPadding(leftInset, getPaddingTop(), rightInset, 0);
+            mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
+                    mHotseatWrapper.getPaddingRight(), bottomInset);
+            mHotseatWrapper.getLayoutParams().height =
+                    mLauncher.getDeviceProfile().hotseatBarSizePx + insets.bottom;
+
+        } else {
+            setPadding(0, getPaddingTop(), 0, 0);
+            mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
+                    mHotseatWrapper.getPaddingRight(),
+                    (int) getResources().getDimension(R.dimen.bottom_sheet_edu_padding));
+            ((TextView) findViewById(R.id.hotseat_edu_heading)).setText(
+                    R.string.hotseat_edu_title_migrate_landscape);
+            ((TextView) findViewById(R.id.hotseat_edu_content)).setText(
+                    R.string.hotseat_edu_message_migrate_landscape);
+        }
     }
 
     private void logUserAction(boolean migrated, int pageIndex) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
index cdaa655..3623e67 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
@@ -37,6 +37,7 @@
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
+import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
 import com.android.launcher3.model.WellbeingModel;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -71,7 +72,16 @@
     static WorkspaceItemInfo dummyInfo(TaskView view) {
         Task task = view.getTask();
 
-        WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
+        WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo(){
+            /**
+             * Helps to log events as {@link LauncherAtom.Task}
+             * instead of {@link LauncherAtom.ItemInfo}.
+             */
+            @Override
+            public LauncherAtom.ItemInfo buildProto() {
+                return view.buildProto();
+            }
+        };
         dummyInfo.intent = new Intent();
         ComponentName component = task.getTopComponent();
         dummyInfo.getIntent().setComponent(component);
@@ -310,6 +320,8 @@
             };
             mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler());
             dismissTaskMenuView(mTarget);
+            mTarget.getStatsLogManager().log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP,
+                    mTaskView.buildProto());
         }
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 7090393..e7b965b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -202,6 +202,12 @@
                 .setStartVelocity(mVelocity)
                 .build(v, VIEW_TRANSLATE_Y);
         springTransY.setStartDelay(startDelay);
+        springTransY.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                v.setTranslationY(0f);
+            }
+        });
         mAnimators.play(springTransY);
 
         v.setAlpha(0);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index 3c9762b..196a7c4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -258,9 +258,9 @@
         mMatrix.postScale(scale, scale);
         mMatrix.postTranslate(insets.left, insets.top);
 
-        // Apply TaskView matrix: scale, translate, scroll
-        mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2);
+        // Apply TaskView matrix: translate, scale, scroll
         mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
+        mMatrix.postScale(mCurveScale, mCurveScale, taskWidth / 2, taskHeight / 2);
         mOrientationState.getOrientationHandler().set(
                 mMatrix, MATRIX_POST_TRANSLATE, mScrollState.scroll);
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index 78ac1cc..3299736 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -227,8 +227,8 @@
     protected void onDraw(Canvas canvas) {
         RectF currentDrawnInsets = mFullscreenParams.mCurrentDrawnInsets;
         canvas.save();
-        canvas.translate(currentDrawnInsets.left, currentDrawnInsets.top);
         canvas.scale(mFullscreenParams.mScale, mFullscreenParams.mScale);
+        canvas.translate(currentDrawnInsets.left, currentDrawnInsets.top);
         // Draw the insets if we're being drawn fullscreen (we do this for quick switch).
         drawOnCanvas(canvas,
                 -currentDrawnInsets.left,
@@ -357,6 +357,7 @@
             mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
             mPaint.setShader(mBitmapShader);
         }
+        getTaskView().updateCurrentFullscreenParams(mPreviewPositionHelper);
         invalidate();
 
         // Update can be called from {@link #onSizeChanged} during layout, post handling of overlay
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index af9d7f7..429ccf5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -223,7 +223,9 @@
         setOutlineProvider(mOutlineProvider);
     }
 
-    /** Builds proto for logging */
+    /**
+     * Builds proto for logging
+     */
     public LauncherAtom.ItemInfo buildProto() {
         ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(getTask().key);
         LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
@@ -953,11 +955,7 @@
         setClipToPadding(!isFullscreen);
 
         TaskThumbnailView thumbnail = getThumbnail();
-        mCurrentFullscreenParams.setProgress(
-                mFullscreenProgress,
-                getRecentsView().getScaleX(),
-                getWidth(), mActivity.getDeviceProfile(),
-                thumbnail.getPreviewPositionHelper());
+        updateCurrentFullscreenParams(thumbnail.getPreviewPositionHelper());
 
         if (!getRecentsView().isTaskIconScaledDown(this)) {
             // Some of the items in here are dependent on the current fullscreen params, but don't
@@ -970,6 +968,14 @@
         invalidateOutline();
     }
 
+    void updateCurrentFullscreenParams(PreviewPositionHelper previewPositionHelper) {
+        mCurrentFullscreenParams.setProgress(
+                mFullscreenProgress,
+                getRecentsView().getScaleX(),
+                getWidth(), mActivity.getDeviceProfile(),
+                previewPositionHelper);
+    }
+
     public boolean isRunningTask() {
         if (getRecentsView() == null) {
             return false;
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 35143c5..a27c127 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -65,8 +65,10 @@
 
     <!-- Hotseat educational strings for users who don't qualify for migration -->
     <string name="hotseat_edu_title_migrate">Get app suggestions on the bottom row of your Home screen</string>
+    <string name="hotseat_edu_title_migrate_landscape">Get app suggestions on favorites row of your Home screen</string>
 
     <string name="hotseat_edu_message_migrate">Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move up to your Home screen. </string>
+    <string name="hotseat_edu_message_migrate_landscape">Easily access your most-used apps right on the Home screen. Suggestions will change based on your routines. Apps in favorites row will move to your Home screen. </string>
     <string name="hotseat_edu_message_migrate_alt">Easily access your most-used apps, right on the Home screen. Suggestions will change based on your routines. Apps on the bottom row will move to a new folder.</string>
 
     <!-- Button text to opt in for fully predicted hotseat -->
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index d4d46fb..5a4292b 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -141,10 +141,10 @@
                 getHierarchy(info) /* hierarchy */,
                 info.getIsWork() /* is_work_profile */,
                 info.getRank() /* rank */,
-                0 /* fromState */,
-                0 /* toState */,
-                null /* edittext */,
-                0 /* cardinality */);
+                info.getFolderIcon().getFromLabelState().getNumber() /* fromState */,
+                info.getFolderIcon().getToLabelState().getNumber() /* toState */,
+                info.getFolderIcon().getLabelInfo() /* edittext */,
+                info.getFolderIcon().getCardinality() /* cardinality */);
     }
 
     /**
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index e11917b..ea0ff8b 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.anim;
 
+import static com.android.launcher3.Utilities.boundToRange;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
@@ -30,8 +31,6 @@
 
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.Utilities;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -54,11 +53,8 @@
      * to float (animation-fraction * total duration) to int conversion.
      */
     public static AnimatorPlaybackController wrap(AnimatorSet anim, long duration) {
-        /**
-         * TODO: use {@link AnimatorSet#setCurrentPlayTime(long)} once b/68382377 is fixed.
-         */
         ArrayList<Holder> childAnims = new ArrayList<>();
-        addAnimationHoldersRecur(anim, SpringProperty.DEFAULT, childAnims);
+        addAnimationHoldersRecur(anim, duration, SpringProperty.DEFAULT, childAnims);
 
         return new AnimatorPlaybackController(anim, duration, childAnims);
     }
@@ -152,7 +148,7 @@
         float scaleInverse = 1 / Math.abs(scale);
         float scaledVelocity = velocity * scaleInverse;
 
-        float nextFrameProgress = Utilities.boundToRange(getProgressFraction()
+        float nextFrameProgress = boundToRange(getProgressFraction()
                 + scaledVelocity * getSingleFrameMs(context), 0f, 1f);
 
         // Update setters for spring
@@ -176,8 +172,8 @@
                 springDuration = Math.max(expectedDurationL, springDuration);
 
                 float expectedDuration = expectedDurationL;
-                h.setter = (a, l) -> a.setCurrentFraction(
-                        mAnimationPlayer.getCurrentPlayTime() / expectedDuration);
+                h.mapper = (progress, globalEndProgress) ->
+                        mAnimationPlayer.getCurrentPlayTime() / expectedDuration;
                 h.anim.setInterpolator(s::getInterpolatedValue);
             }
         }
@@ -237,9 +233,9 @@
         if (mTargetCancelled) {
             return;
         }
-        long playPos = clampDuration(fraction);
+        float progress = boundToRange(fraction, 0, 1);
         for (Holder holder : mChildAnimations) {
-            holder.setter.set(holder.anim, playPos);
+            holder.setProgress(progress);
         }
     }
 
@@ -361,14 +357,14 @@
     }
 
     /**
-     * Interface for setting position of value animator
+     * Interface for mapping progress to animation progress
      */
-    private interface PositionSetter {
+    private interface ProgressMapper {
 
-        PositionSetter DEFAULT = (anim, playPos) ->
-                anim.setCurrentPlayTime(Math.min(playPos, anim.getDuration()));
+        ProgressMapper DEFAULT = (progress, globalEndProgress) ->
+                progress > globalEndProgress ? 1 : (progress / globalEndProgress);
 
-        void set(ValueAnimator anim, long position);
+        float getProgress(float progress, float globalProgress);
     }
 
     /**
@@ -382,27 +378,34 @@
 
         public final TimeInterpolator interpolator;
 
-        public PositionSetter setter;
+        public final float globalEndProgress;
 
-        Holder(Animator anim, SpringProperty springProperty) {
+        public ProgressMapper mapper;
+
+        Holder(Animator anim, float globalDuration, SpringProperty springProperty) {
             this.anim = (ValueAnimator) anim;
             this.springProperty = springProperty;
             this.interpolator = this.anim.getInterpolator();
-            this.setter = PositionSetter.DEFAULT;
+            this.globalEndProgress = anim.getDuration() / globalDuration;
+            this.mapper = ProgressMapper.DEFAULT;
+        }
+
+        public void setProgress(float progress) {
+            anim.setCurrentFraction(mapper.getProgress(progress, globalEndProgress));
         }
 
         public void reset() {
             anim.setInterpolator(interpolator);
-            setter = PositionSetter.DEFAULT;
+            mapper = ProgressMapper.DEFAULT;
         }
     }
 
-    static void addAnimationHoldersRecur(
-            Animator anim, SpringProperty springProperty, ArrayList<Holder> out) {
+    static void addAnimationHoldersRecur(Animator anim, long globalDuration,
+            SpringProperty springProperty, ArrayList<Holder> out) {
         long forceDuration = anim.getDuration();
         TimeInterpolator forceInterpolator = anim.getInterpolator();
         if (anim instanceof ValueAnimator) {
-            out.add(new Holder(anim, springProperty));
+            out.add(new Holder(anim, globalDuration, springProperty));
         } else if (anim instanceof AnimatorSet) {
             for (Animator child : ((AnimatorSet) anim).getChildAnimations()) {
                 if (forceDuration > 0) {
@@ -411,7 +414,7 @@
                 if (forceInterpolator != null) {
                     child.setInterpolator(forceInterpolator);
                 }
-                addAnimationHoldersRecur(child, springProperty, out);
+                addAnimationHoldersRecur(child, globalDuration, springProperty, out);
             }
         } else {
             throw new RuntimeException("Unknown animation type " + anim);
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 0f04104..afeb341 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -70,7 +70,7 @@
 
     public void add(Animator a, SpringProperty springProperty) {
         mAnim.play(a);
-        addAnimationHoldersRecur(a, springProperty, mAnimHolders);
+        addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
     }
 
     public void finish(boolean isSuccess, int logAction) {
@@ -150,7 +150,7 @@
         }
         if (mAnimHolders.isEmpty()) {
             // Add a dummy animation to that the duration is respected
-            add(ValueAnimator.ofFloat(0, 1));
+            add(ValueAnimator.ofFloat(0, 1).setDuration(mDuration));
         }
         return mAnim;
     }
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 85013d7..f07cf94 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -104,15 +104,20 @@
                 + "shortcut within longpress popup window.")
         LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP(514),
 
-        @UiEvent(doc = "User opened app info of the package by tapping on appinfo system shortcut "
-                + "within longpress popup window.")
+        @UiEvent(doc = "User tapped on app info system shortcut.")
         LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP(515),
 
         @UiEvent(doc = "User tapped on split screen icon on a task menu.")
         LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP(518),
 
         @UiEvent(doc = "User tapped on free form icon on a task menu.")
-        LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP(519);
+        LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP(519),
+
+        @UiEvent(doc = "User tapped on pause app system shortcut.")
+        LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP(521),
+
+        @UiEvent(doc = "User tapped on pin system shortcut.")
+        LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP(522);
         // ADD MORE
 
         private final int mId;
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 3875d2e..58251e8 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.popup;
 
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import android.annotation.TargetApi;
@@ -76,6 +77,8 @@
     @Override
     public void onClick(View view) {
         AbstractFloatingView.closeAllOpenViews(mTarget);
+        mTarget.getStatsLogManager()
+                .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP, mItemInfo.buildProto());
 
         final String actionIdentity = mAction.getTitle() + ", "
                 + mItemInfo.getTargetComponent().getPackageName();
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 58ed5e8..ea8caf5 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -29,6 +29,7 @@
 import com.android.launcher3.widget.WidgetsBottomSheet;
 
 import java.util.List;
+
 /**
  * Represents a system shortcut for a given app. The shortcut should have a label and icon, and an
  * onClickListener that depends on the item that the shortcut services.
@@ -142,8 +143,8 @@
             mTarget.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
                     ControlType.APPINFO_TARGET, view);
             // TODO(thiruram): Fix missing container info when item is inside folder.
-            mTarget.getStatsLogManager().log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP,
-                    mItemInfo.buildProto());
+            mTarget.getStatsLogManager()
+                    .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP, mItemInfo.buildProto());
         }
     }