Merge "Import translations. DO NOT MERGE ANYWHERE" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index a8a085b..6e2fadd 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -176,6 +176,7 @@
     private static final int LAUNCHER_RESUME_START_DELAY = 100;
     private static final int CLOSING_TRANSITION_DURATION_MS = 250;
     public static final int SPLIT_LAUNCH_DURATION = 370;
+    public static final int SPLIT_DIVIDER_ANIM_DURATION = 100;
 
     public static final int CONTENT_ALPHA_DURATION = 217;
     protected static final int CONTENT_SCALE_DURATION = 350;
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index f9a0bb1..4d06956 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -64,6 +64,7 @@
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.util.IntSparseArrayMap;
 import com.android.launcher3.util.PersistedItemArray;
+import com.android.quickstep.logging.SettingsChangeLogger;
 import com.android.quickstep.logging.StatsLogCompatManager;
 import com.android.systemui.shared.system.SysUiStatsLog;
 
@@ -97,10 +98,12 @@
     private final InvariantDeviceProfile mIDP;
     private final AppEventProducer mAppEventProducer;
     private final StatsManager mStatsManager;
+    private final Context mContext;
 
     protected boolean mActive = false;
 
     public QuickstepModelDelegate(Context context) {
+        mContext = context;
         mAppEventProducer = new AppEventProducer(context, this::onAppTargetEvent);
 
         mIDP = InvariantDeviceProfile.INSTANCE.get(context);
@@ -210,6 +213,7 @@
                                         "Successfully logged %d workspace items with instanceId=%d",
                                         itemsIdMap.size(), instanceId.getId()));
                         additionalSnapshotEvents(instanceId);
+                        SettingsChangeLogger.INSTANCE.get(mContext).logSnapshot(instanceId);
                         return StatsManager.PULL_SUCCESS;
                     }
             );
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 5c266bb..c7f1edd 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -831,7 +831,8 @@
         // Notify when the animation starts
         flushOnRecentsAnimationAndLauncherBound();
 
-        TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, false);
+        TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
+                false /*shown*/, true /*animate*/);
 
         // Only add the callback to enable the input consumer after we actually have the controller
         mStateCallback.runOnceAtState(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
@@ -848,7 +849,8 @@
         mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
 
         if (mRecentsAnimationTargets != null) {
-            TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, true);
+            TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
+                    true /*shown*/, true /*animate*/);
         }
 
         // Defer clearing the controller and the targets until after we've updated the state
@@ -998,8 +1000,8 @@
                     mStateCallback.setState(STATE_RESUME_LAST_TASK);
                 }
                 if (mRecentsAnimationTargets != null) {
-                    TaskViewUtils.setSplitAuxiliarySurfacesShown(
-                            mRecentsAnimationTargets.nonApps, true);
+                    TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
+                            true /*shown*/, true /*animate*/);
                 }
                 break;
         }
@@ -1651,7 +1653,8 @@
         mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
 
         if (mRecentsAnimationTargets != null) {
-            TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, true);
+            TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
+                    true /*shown*/, true /*animate*/);
         }
 
         // Leave the pending invisible flag, as it may be used by wallpaper open animation.
@@ -1917,7 +1920,8 @@
     @Override
     public void onRecentsAnimationFinished(RecentsAnimationController controller) {
         if (!controller.getFinishTargetIsLauncher()) {
-            TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, true);
+            TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps,
+                    true /*shown*/, true /*animate*/);
         }
         mRecentsAnimationController = null;
         mRecentsAnimationTargets = null;
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
index 65847f1..a551f55 100644
--- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -24,8 +24,6 @@
 
 import com.android.launcher3.BuildConfig;
 import com.android.launcher3.MainProcessInitializer;
-import com.android.launcher3.util.Executors;
-import com.android.quickstep.logging.SettingsChangeLogger;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.systemui.shared.system.ThreadedRendererCompat;
 
@@ -62,9 +60,5 @@
         // Elevate GPU priority for Quickstep and Remote animations.
         ThreadedRendererCompat.setContextPriority(
                 ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
-
-        // Initialize settings logger after a default timeout
-        Executors.MAIN_EXECUTOR.getHandler()
-                .postDelayed(() -> new SettingsChangeLogger(context), SETUP_DELAY_MILLIS);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index e69330a..d3b17f8 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -20,6 +20,7 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
 import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
 
 import android.app.ActivityManager;
 import android.content.Context;
@@ -27,6 +28,7 @@
 import android.os.Bundle;
 import android.os.SystemProperties;
 import android.util.Log;
+import android.view.RemoteAnimationTarget;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
@@ -42,6 +44,7 @@
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 
+import java.util.Arrays;
 import java.util.HashMap;
 
 public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
@@ -150,6 +153,17 @@
             public void onTasksAppeared(RemoteAnimationTargetCompat[] appearedTaskTargets) {
                 RemoteAnimationTargetCompat appearedTaskTarget = appearedTaskTargets[0];
                 BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
+                // Convert appTargets to type RemoteAnimationTarget for all apps except Home app
+                RemoteAnimationTarget[] nonHomeApps = Arrays.stream(appearedTaskTargets)
+                        .filter(remoteAnimationTarget ->
+                                remoteAnimationTarget.activityType != ACTIVITY_TYPE_HOME)
+                        .map(RemoteAnimationTargetCompat::unwrap)
+                        .toArray(RemoteAnimationTarget[]::new);
+
+                RemoteAnimationTarget[] nonAppTargets =
+                        SystemUiProxy.INSTANCE.getNoCreate()
+                                .onGoingToRecentsLegacy(false, nonHomeApps);
+
                 if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
                         && activityInterface.getCreatedActivity() != null) {
                     RecentsView recentsView =
@@ -158,7 +172,7 @@
                         recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId,
                                 appearedTaskTargets,
                                 new RemoteAnimationTargetCompat[0] /* wallpaper */,
-                                new RemoteAnimationTargetCompat[0] /* nonApps */);
+                                RemoteAnimationTargetCompat.wrap(nonAppTargets) /* nonApps */);
                         return;
                     }
                 }
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 97fc6d7..14f3ec4 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -28,6 +28,7 @@
 import static com.android.launcher3.QuickstepTransitionManager.NAV_FADE_IN_INTERPOLATOR;
 import static com.android.launcher3.QuickstepTransitionManager.NAV_FADE_OUT_INTERPOLATOR;
 import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
+import static com.android.launcher3.QuickstepTransitionManager.SPLIT_DIVIDER_ANIM_DURATION;
 import static com.android.launcher3.QuickstepTransitionManager.SPLIT_LAUNCH_DURATION;
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -536,7 +537,8 @@
                 nonAppTargets, depthController, pa);
         if (launcherClosing) {
             // TODO(b/182592057): differentiate between "restore split" vs "launch fullscreen app"
-            TaskViewUtils.setSplitAuxiliarySurfacesShown(nonAppTargets, true);
+            TaskViewUtils.setSplitAuxiliarySurfacesShown(nonAppTargets,
+                    true /*shown*/, true /*animate*/, pa);
         }
 
         Animator childStateAnimation = null;
@@ -592,19 +594,88 @@
     }
 
     public static void setSplitAuxiliarySurfacesShown(RemoteAnimationTargetCompat[] nonApps,
-            boolean shown) {
-        // TODO(b/182592057): make this part of the animations instead.
-        if (nonApps != null && nonApps.length > 0) {
-            SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-            for (int i = 0; i < nonApps.length; ++i) {
-                final RemoteAnimationTargetCompat targ = nonApps[i];
-                final SurfaceControl leash = targ.leash.getSurfaceControl();
-                if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
-                    t.setVisibility(leash, shown);
+            boolean shown, boolean animate) {
+        setSplitAuxiliarySurfacesShown(nonApps, shown, animate,null);
+    }
+
+    private static void setSplitAuxiliarySurfacesShown(
+            @NonNull RemoteAnimationTargetCompat[] nonApps, boolean shown, boolean animate,
+            @Nullable PendingAnimation splitLaunchAnimation) {
+        if (nonApps == null || nonApps.length == 0) {
+            return;
+        }
+
+        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        SurfaceControl[] auxiliarySurfaces = new SurfaceControl[nonApps.length];
+        boolean hasSurfaceToAnimate = false;
+        for (int i = 0; i < nonApps.length; ++i) {
+            final RemoteAnimationTargetCompat targ = nonApps[i];
+            final SurfaceControl leash = targ.leash.getSurfaceControl();
+            if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
+                auxiliarySurfaces[i] = leash;
+                hasSurfaceToAnimate = true;
+            }
+        }
+        if (!hasSurfaceToAnimate) {
+            return;
+        }
+
+        if (!animate) {
+            for (SurfaceControl leash : auxiliarySurfaces) {
+                t.setAlpha(leash, shown ? 1 : 0);
+                if (shown) {
+                    t.show(leash);
+                } else {
+                    t.hide(leash);
                 }
             }
             t.apply();
-            t.close();
+            return;
+        }
+
+        ValueAnimator dockFadeAnimator = ValueAnimator.ofFloat(0f, 1f);
+        dockFadeAnimator.addUpdateListener(valueAnimator -> {
+            float progress = valueAnimator.getAnimatedFraction();
+            for (SurfaceControl leash : auxiliarySurfaces) {
+                t.setAlpha(leash, shown ? progress : 1 - progress);
+            }
+            t.apply();
+        });
+        dockFadeAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                super.onAnimationStart(animation);
+                if (shown) {
+                    for (SurfaceControl leash : auxiliarySurfaces) {
+                        t.setAlpha(leash, 0);
+                        t.show(leash);
+                    }
+                    t.apply();
+                }
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                if (!shown) {
+                    for (SurfaceControl leash : auxiliarySurfaces) {
+                        t.hide(leash);
+                    }
+                    t.apply();
+                }
+                t.close();
+            }
+        });
+        dockFadeAnimator.setDuration(SPLIT_DIVIDER_ANIM_DURATION);
+        if (splitLaunchAnimation != null) {
+            // If split apps are launching, we want to delay showing the divider bar until the very
+            // end once the apps are mostly in place. This is because we aren't moving the divider
+            // leash in the relative position with the launching apps.
+            dockFadeAnimator.setStartDelay(
+                    splitLaunchAnimation.getDuration() - SPLIT_DIVIDER_ANIM_DURATION);
+            splitLaunchAnimation.add(dockFadeAnimator);
+        } else {
+            dockFadeAnimator.start();
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 7ae0fc8..a0cd0d7 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -40,10 +40,11 @@
 import com.android.launcher3.AutoInstallsLayout;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.logging.InstanceIdSequence;
+import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.model.DeviceGridState;
+import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SettingsCache;
 import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.SysUINavigationMode.Mode;
@@ -53,12 +54,19 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.Optional;
 
 /**
  * Utility class to log launcher settings changes
  */
 public class SettingsChangeLogger implements
         NavigationModeChangeListener, OnSharedPreferenceChangeListener {
+  
+    /**
+     * Singleton instance
+     */
+    public static MainThreadInitializedObject<SettingsChangeLogger> INSTANCE =
+            new MainThreadInitializedObject<>(SettingsChangeLogger::new);
 
     private static final String TAG = "SettingsChangeLogger";
     private static final String ROOT_TAG = "androidx.preference.PreferenceScreen";
@@ -66,12 +74,15 @@
 
     private final Context mContext;
     private final ArrayMap<String, LoggablePref> mLoggablePrefs;
+    private final StatsLogManager mStatsLogManager;
 
     private Mode mNavMode;
-    private boolean mNotificationDotsEnabled;
+    private StatsLogManager.LauncherEvent mNotificationDotsEvent;
+    private StatsLogManager.LauncherEvent mHomeScreenSuggestionEvent;
 
-    public SettingsChangeLogger(Context context) {
+    private SettingsChangeLogger(Context context) {
         mContext = context;
+        mStatsLogManager = StatsLogManager.newInstance(mContext);
         mLoggablePrefs = loadPrefKeys(context);
         mNavMode = SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
 
@@ -118,14 +129,21 @@
     }
 
     private void onNotificationDotsChanged(boolean isDotsEnabled) {
-        mNotificationDotsEnabled = isDotsEnabled;
-        dispatchUserEvent();
+        StatsLogManager.LauncherEvent mEvent =
+                isDotsEnabled ? LAUNCHER_NOTIFICATION_DOT_ENABLED
+                        : LAUNCHER_NOTIFICATION_DOT_DISABLED;
+
+        // Log only when the setting is actually changed and not during initialization.
+        if (mNotificationDotsEvent != null && mNotificationDotsEvent != mEvent) {
+            mStatsLogManager.logger().log(mNotificationDotsEvent);
+        }
+        mNotificationDotsEvent = mEvent;
     }
 
     @Override
     public void onNavigationModeChanged(Mode newMode) {
         mNavMode = newMode;
-        dispatchUserEvent();
+        mStatsLogManager.logger().log(newMode.launcherEvent);
     }
 
     @Override
@@ -134,27 +152,27 @@
                 || KEY_WORKSPACE_SIZE.equals(key)
                 || KEY_THEMED_ICONS.equals(key)
                 || mLoggablePrefs.containsKey(key)) {
-            dispatchUserEvent();
+
+            mHomeScreenSuggestionEvent = getDevicePrefs(mContext)
+                    .getBoolean(LAST_PREDICTION_ENABLED_STATE, true)
+                    ? LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED
+                    : LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED;
+
+            mStatsLogManager.logger().log(mHomeScreenSuggestionEvent);
         }
     }
 
-    private void dispatchUserEvent() {
-        StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
-                .withInstanceId(new InstanceIdSequence().newInstanceId());
+    /**
+     * Takes snapshot of all eligible launcher settings and log them with the provided instance ID.
+     */
+    public void logSnapshot(InstanceId snapshotInstanceId) {
+        StatsLogger logger = mStatsLogManager.logger().withInstanceId(snapshotInstanceId);
 
-        logger.log(mNotificationDotsEnabled
-                ? LAUNCHER_NOTIFICATION_DOT_ENABLED
-                : LAUNCHER_NOTIFICATION_DOT_DISABLED);
-        logger.log(mNavMode.launcherEvent);
-        logger.log(getDevicePrefs(mContext).getBoolean(LAST_PREDICTION_ENABLED_STATE, true)
-                ? LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED
-                : LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED);
-
-        StatsLogManager.LauncherEvent gridSizeChangedEvent =
-                new DeviceGridState(mContext).getWorkspaceSizeEvent();
-        if (gridSizeChangedEvent != null) {
-            logger.log(gridSizeChangedEvent);
-        }
+        Optional.ofNullable(mNotificationDotsEvent).ifPresent(logger::log);
+        Optional.ofNullable(mNavMode).map(mode -> mode.launcherEvent).ifPresent(logger::log);
+        Optional.ofNullable(mHomeScreenSuggestionEvent).ifPresent(logger::log);
+        Optional.ofNullable(new DeviceGridState(mContext).getWorkspaceSizeEvent()).ifPresent(
+                logger::log);
 
         SharedPreferences prefs = getPrefs(mContext);
         if (FeatureFlags.ENABLE_THEMED_ICONS.get()) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 4ec16ad..10efa3e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -4246,8 +4246,10 @@
         mPendingAnimation.addEndListener(isSuccess -> {
             if (isSuccess) {
                 if (tv.getTaskIds()[1] != -1) {
+                    // TODO(b/194414938): make this part of the animations instead.
                     TaskViewUtils.setSplitAuxiliarySurfacesShown(mRemoteTargetHandles[0]
-                            .getTransformParams().getTargetSet().nonApps, true);
+                            .getTransformParams().getTargetSet().nonApps,
+                            true /*shown*/, false /*animate*/);
                 }
                 if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
                     finishRecentsAnimation(false /* toRecents */, null);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index a71e558..9887630 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -628,11 +628,8 @@
                         Arrays.stream(topLeftParams.getTargetSet().wallpapers),
                         Arrays.stream(rightBottomParams.getTargetSet().wallpapers))
                         .toArray(RemoteAnimationTargetCompat[]::new);
-                RemoteAnimationTargetCompat[] nonApps = Stream.concat(
-                        Arrays.stream(topLeftParams.getTargetSet().nonApps),
-                        Arrays.stream(rightBottomParams.getTargetSet().nonApps))
-                        .toArray(RemoteAnimationTargetCompat[]::new);
-                targets = new RemoteAnimationTargets(apps, wallpapers, nonApps,
+                targets = new RemoteAnimationTargets(apps, wallpapers,
+                        topLeftParams.getTargetSet().nonApps,
                         topLeftParams.getTargetSet().targetMode);
             }
             if (targets == null) {