Better handling transparent activities

> Only hiding the task associated with the current task, instead of hiding all tasks
> Maintaining a state for hidden task so that it does not get reset when alpha is changed due
  to some other reason.

Bug: 77830202
Change-Id: I202e99b153c6f9e3a8d9c68d6844672b3bff41e9
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 41f5bb8..8e2f2f1 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 28c950b..f7e45d3 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -23,6 +23,7 @@
 import static android.view.MotionEvent.INVALID_POINTER_ID;
 
 import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_DRAG_SLOP_PX;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 
 import android.annotation.TargetApi;
 import android.app.ActivityManager.RunningTaskInfo;
@@ -45,6 +46,7 @@
 
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.util.TraceHelper;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.AssistDataReceiver;
 import com.android.systemui.shared.system.BackgroundExecutor;
@@ -229,8 +231,9 @@
                             Rect minimizedHomeBounds) {
                         if (mInteractionHandler == handler) {
                             TraceHelper.partitionSection("RecentsController", "Received");
-                            handler.onRecentsAnimationStart(controller, apps, homeContentInsets,
-                                    minimizedHomeBounds);
+                            handler.onRecentsAnimationStart(controller,
+                                    new RemoteAnimationTargetSet(apps, MODE_CLOSING),
+                                    homeContentInsets, minimizedHomeBounds);
                         } else {
                             TraceHelper.endSection("RecentsController", "Finishing no handler");
                             controller.finish(false /* toHome */);
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 5563aed..663a005 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -53,6 +53,7 @@
 import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper;
 import com.android.quickstep.util.ClipAnimationHelper;
 import com.android.quickstep.util.RemoteAnimationProvider;
+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;
@@ -279,15 +280,13 @@
                 return anim;
             }
 
-            RemoteAnimationTargetCompat closingTarget = null;
+            RemoteAnimationTargetSet targetSet =
+                    new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING);
+
+
             // Use the top closing app to determine the insets for the animation
-            for (RemoteAnimationTargetCompat target : targetCompats) {
-                if (target.mode == MODE_CLOSING) {
-                    closingTarget = target;
-                    break;
-                }
-            }
-            if (closingTarget == null) {
+            RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
+            if (runningTaskTarget == null) {
                 Log.e(TAG, "No closing app");
                 anim.play(ValueAnimator.ofInt(0, 1).setDuration(100));
                 return anim;
@@ -302,20 +301,18 @@
             rootView.getLocationOnScreen(loc);
             Rect homeBounds = new Rect(loc[0], loc[1],
                     loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
-            clipHelper.updateSource(homeBounds, closingTarget);
+            clipHelper.updateSource(homeBounds, runningTaskTarget);
 
             Rect targetRect = new Rect();
             mHelper.getSwipeUpDestinationAndLength(
                     mActivity.getDeviceProfile(), mActivity, targetRect);
             clipHelper.updateTargetRect(targetRect);
 
-
             ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
             valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
             valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
-            valueAnimator.addUpdateListener((v) -> {
-                clipHelper.applyTransform(targetCompats, (float) v.getAnimatedValue());
-            });
+            valueAnimator.addUpdateListener((v) ->
+                clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue()));
             anim.play(valueAnimator);
             return anim;
         }
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
index 12f8d52..ebe2311 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -16,9 +16,9 @@
 package com.android.quickstep;
 
 import com.android.launcher3.util.TraceHelper;
+import com.android.quickstep.util.RemoteAnimationTargetSet;
 import com.android.systemui.shared.system.BackgroundExecutor;
 import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
 /**
  * Wrapper around RecentsAnimationController to help with some synchronization
@@ -26,17 +26,17 @@
 public class RecentsAnimationWrapper {
 
     public RecentsAnimationControllerCompat controller;
-    public RemoteAnimationTargetCompat[] targets;
+    public RemoteAnimationTargetSet targetSet;
 
     private boolean mInputConsumerEnabled = false;
     private boolean mBehindSystemBars = true;
     private boolean mSplitScreenMinimized = false;
 
     public synchronized void setController(
-            RecentsAnimationControllerCompat controller, RemoteAnimationTargetCompat[] targets) {
+            RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) {
         TraceHelper.partitionSection("RecentsController", "Set controller " + controller);
         this.controller = controller;
-        this.targets = targets;
+        this.targetSet = targetSet;
 
         if (mInputConsumerEnabled) {
             enableInputConsumer();
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index ce16adf..2709523 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -24,7 +24,6 @@
 import static com.android.systemui.shared.recents.utilities.Utilities
         .postAtFrontOfQueueAsynchronously;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
@@ -48,9 +47,9 @@
 import android.view.animation.Interpolator;
 
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseActivity;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.MainThreadExecutor;
 import com.android.launcher3.R;
@@ -67,6 +66,7 @@
 import com.android.quickstep.ActivityControlHelper.LayoutListener;
 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;
@@ -76,7 +76,6 @@
 import com.android.systemui.shared.system.LatencyTrackerCompat;
 import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-import com.android.systemui.shared.system.TransactionCompat;
 import com.android.systemui.shared.system.WindowCallbacksCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 
@@ -347,6 +346,7 @@
         }
 
         mRecentsView.showTask(mRunningTaskId);
+        mRecentsView.setRunningTaskHidden(true);
         mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
         mLayoutListener.open();
         mStateCallback.setState(STATE_LAUNCHER_STARTED);
@@ -436,7 +436,8 @@
                 Interpolator interpolator = mInteractionType == INTERACTION_QUICK_SCRUB
                         ? ACCEL_2 : LINEAR;
                 float interpolated = interpolator.getInterpolation(shift);
-                mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targets, interpolated);
+                mClipAnimationHelper.applyTransform(
+                        mRecentsAnimationWrapper.targetSet, interpolated);
             }
         }
 
@@ -478,36 +479,37 @@
     }
 
     public void onRecentsAnimationStart(RecentsAnimationControllerCompat controller,
-            RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, Rect minimizedHomeBounds) {
-        if (apps != null) {
-            // Use the top closing app to determine the insets for the animation
-            for (RemoteAnimationTargetCompat target : apps) {
-                if (target.mode == MODE_CLOSING) {
-                    DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
-                    final Rect overviewStackBounds;
+            RemoteAnimationTargetSet targets, Rect homeContentInsets, Rect minimizedHomeBounds) {
+        LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+        InvariantDeviceProfile idp = appState == null ?
+                new InvariantDeviceProfile(mContext) : appState.getInvariantDeviceProfile();
+        DeviceProfile dp = idp.getDeviceProfile(mContext);
+        final Rect overviewStackBounds;
+        RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mRunningTaskId);
 
-                    if (minimizedHomeBounds != null) {
-                        overviewStackBounds = mActivityControlHelper
-                                .getOverviewWindowBounds(minimizedHomeBounds, target);
-                        dp = dp.getMultiWindowProfile(mContext,
-                                new Point(minimizedHomeBounds.width(), minimizedHomeBounds.height()));
-                        dp.updateInsets(homeContentInsets);
-                    } else {
-                        overviewStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx);
-                        // TODO: Workaround for an existing issue where the home content insets are
-                        // not valid immediately after rotation, just use the stable insets for now
-                        Rect insets = new Rect();
-                        WindowManagerWrapper.getInstance().getStableInsets(insets);
-                        dp = dp.copy(mContext);
-                        dp.updateInsets(insets);
-                    }
-
-                    mClipAnimationHelper.updateSource(overviewStackBounds, target);
-                    initTransitionEndpoints(dp);
-                }
-            }
+        if (minimizedHomeBounds != null && runningTaskTarget != null) {
+            overviewStackBounds = mActivityControlHelper
+                    .getOverviewWindowBounds(minimizedHomeBounds, runningTaskTarget);
+            dp = dp.getMultiWindowProfile(mContext,
+                    new Point(minimizedHomeBounds.width(), minimizedHomeBounds.height()));
+            dp.updateInsets(homeContentInsets);
+        } else {
+            overviewStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx);
+            // TODO: Workaround for an existing issue where the home content insets are
+            // not valid immediately after rotation, just use the stable insets for now
+            Rect insets = new Rect();
+            WindowManagerWrapper.getInstance().getStableInsets(insets);
+            dp = dp.copy(mContext);
+            dp.updateInsets(insets);
         }
-        mRecentsAnimationWrapper.setController(controller, apps);
+
+        if (runningTaskTarget != null) {
+            mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget);
+        }
+        initTransitionEndpoints(dp);
+
+
+        mRecentsAnimationWrapper.setController(controller, targets);
         setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
     }
 
@@ -641,6 +643,7 @@
         mLauncherTransitionController = null;
         mLayoutListener.finish();
 
+        mRecentsView.setRunningTaskHidden(false);
         mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
     }
 
@@ -666,29 +669,22 @@
 
         synchronized (mRecentsAnimationWrapper) {
             if (mRecentsAnimationWrapper.controller != null) {
-                for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) {
-                    if (app.mode == MODE_CLOSING) {
-                        // Update the screenshot of the task
-                        ThumbnailData thumbnail =
-                                mRecentsAnimationWrapper.controller.screenshotTask(app.taskId);
-                        final TaskView taskView =
-                                mRecentsView.updateThumbnail(app.taskId, thumbnail);
-                        if (taskView != null) {
-                            taskView.setAlpha(1);
+                // Update the screenshot of the task
+                ThumbnailData thumbnail =
+                        mRecentsAnimationWrapper.controller.screenshotTask(mRunningTaskId);
+                final TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, thumbnail);
+                mRecentsView.setRunningTaskHidden(false);
+                if (taskView != null) {
+                    // Defer finishing the animation until the next launcher frame with the
+                    // new thumbnail
+                    finishTransitionPosted = new WindowCallbacksCompat(taskView) {
 
-                            // Defer finishing the animation until the next launcher frame with the
-                            // new thumbnail
-                            finishTransitionPosted = new WindowCallbacksCompat(taskView) {
-
-                                @Override
-                                public void onPostDraw(Canvas canvas) {
-                                    finishTransitionRunnable.run();
-                                    detach();
-                                }
-                            }.attach();
-                            break;
+                        @Override
+                        public void onPostDraw(Canvas canvas) {
+                            finishTransitionRunnable.run();
+                            detach();
                         }
-                    }
+                    }.attach();
                 }
             }
         }
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index 493e9e2..9276d238 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -15,8 +15,6 @@
  */
 package com.android.quickstep.util;
 
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
-
 import android.graphics.Matrix;
 import android.graphics.Matrix.ScaleToFit;
 import android.graphics.Rect;
@@ -55,10 +53,9 @@
     private final RectFEvaluator mRectFEvaluator = new RectFEvaluator();
     private final Matrix mTmpMatrix = new Matrix();
 
-
     public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
         mHomeStackBounds.set(homeStackBounds);
-        mSourceInsets.set(target.getContentInsets());
+        mSourceInsets.set(target.contentInsets);
         mSourceStackBounds.set(target.sourceContainerBounds);
 
         // TODO: Should sourceContainerBounds already have this offset?
@@ -91,7 +88,7 @@
         mSourceRect.set(scaledTargetRect);
     }
 
-    public void applyTransform(RemoteAnimationTargetCompat[] targets, float progress) {
+    public void applyTransform(RemoteAnimationTargetSet targetSet, float progress) {
         RectF currentRect;
         synchronized (mTargetRect) {
             currentRect =  mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
@@ -109,17 +106,14 @@
         mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);
 
         TransactionCompat transaction = new TransactionCompat();
-        for (RemoteAnimationTargetCompat app : targets) {
-            if (app.mode == MODE_CLOSING) {
-                mTmpMatrix.postTranslate(app.position.x, app.position.y);
-                transaction.setMatrix(app.leash, mTmpMatrix)
-                        .setWindowCrop(app.leash, mClipRect);
-                if (app.isNotInRecents) {
-                    transaction.setAlpha(app.leash, 1 - progress);
-                }
-
-                transaction.show(app.leash);
+        for (RemoteAnimationTargetCompat app : targetSet.apps) {
+            mTmpMatrix.postTranslate(app.position.x, app.position.y);
+            transaction.setMatrix(app.leash, mTmpMatrix)
+                    .setWindowCrop(app.leash, mClipRect);
+            if (app.isNotInRecents) {
+                transaction.setAlpha(app.leash, 1 - progress);
             }
+            transaction.show(app.leash);
         }
         transaction.setEarlyWakeup();
         transaction.apply();
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java
new file mode 100644
index 0000000..fc889e5
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+import java.util.ArrayList;
+
+/**
+ * Holds a collection of RemoteAnimationTargets, filtered by different properties.
+ */
+public class RemoteAnimationTargetSet {
+
+    public final boolean allTransparent;
+    public final RemoteAnimationTargetCompat[] apps;
+
+    public RemoteAnimationTargetSet(RemoteAnimationTargetCompat[] apps, int targetMode) {
+        boolean allTransparent = true;
+
+        ArrayList<RemoteAnimationTargetCompat> filteredApps = new ArrayList<>();
+        if (apps != null) {
+            for (RemoteAnimationTargetCompat target : apps) {
+                if (target.mode == targetMode) {
+                    allTransparent &= target.isTranslucent;
+                    filteredApps.add(target);
+                }
+            }
+        }
+
+        this.allTransparent = allTransparent;
+        this.apps = filteredApps.toArray(new RemoteAnimationTargetCompat[filteredApps.size()]);
+    }
+
+    public RemoteAnimationTargetCompat findTask(int taskId) {
+        for (RemoteAnimationTargetCompat target : apps) {
+            if (target.taskId == taskId) {
+                return target;
+            }
+        }
+        return null;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index a3f10f0..2e70e45 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -160,6 +160,7 @@
 
     // Only valid until the launcher state changes to NORMAL
     private int mRunningTaskId = -1;
+    private boolean mRunningTaskTileHidden;
     private Task mTmpRunningTask;
 
     private boolean mFirstTaskIconScaledDown = false;
@@ -238,14 +239,11 @@
     }
 
     public TaskView updateThumbnail(int taskId, ThumbnailData thumbnailData) {
-        for (int i = 0; i < getChildCount(); i++) {
-            final TaskView taskView = (TaskView) getChildAt(i);
-            if (taskView.getTask().key.id == taskId) {
-                taskView.onTaskDataLoaded(taskView.getTask(), thumbnailData);
-                return taskView;
-            }
+        TaskView taskView = getTaskView(taskId);
+        if (taskView != null) {
+            taskView.onTaskDataLoaded(taskView.getTask(), thumbnailData);
         }
-        return null;
+        return taskView;
     }
 
     @Override
@@ -387,6 +385,9 @@
                 taskView.resetVisualProperties();
             }
         }
+        if (mRunningTaskTileHidden) {
+            setRunningTaskHidden(mRunningTaskTileHidden);
+        }
 
         updateCurveProperties();
         // Update the set of visible task's data
@@ -524,8 +525,10 @@
     protected abstract void onAllTasksRemoved();
 
     public void reset() {
-        unloadVisibleTaskData();
         mRunningTaskId = -1;
+        mRunningTaskTileHidden = false;
+
+        unloadVisibleTaskData();
         setCurrentPage(0);
 
         OverviewCallbacks.get(getContext()).onResetOverview();
@@ -562,12 +565,17 @@
                     new ActivityManager.TaskDescription(), 0, new ComponentName("", ""), false);
             taskView.bind(mTmpRunningTask);
         }
-        setCurrentTask(mRunningTaskId);
+        setCurrentTask(runningTaskId);
+    }
 
-        // Hide the task that we are animating into, ignore if there is no associated task (ie. the
-        // assistant)
-        if (getPageAt(mCurrentPage) != null) {
-            getPageAt(mCurrentPage).setAlpha(0);
+    /**
+     * Hides the tile associated with {@link #mRunningTaskId}
+     */
+    public void setRunningTaskHidden(boolean isHidden) {
+        mRunningTaskTileHidden = isHidden;
+        TaskView runningTask = getTaskView(mRunningTaskId);
+        if (runningTask != null) {
+            runningTask.setAlpha(isHidden ? 0 : mContentAlpha);
         }
     }
 
@@ -575,7 +583,13 @@
      * Similar to {@link #showTask(int)} but does not put any restrictions on the first tile.
      */
     public void setCurrentTask(int runningTaskId) {
-        mRunningTaskId = runningTaskId;
+        if (mRunningTaskTileHidden) {
+            setRunningTaskHidden(false);
+            mRunningTaskId = runningTaskId;
+            setRunningTaskHidden(true);
+        } else {
+            mRunningTaskId = runningTaskId;
+        }
         setCurrentPage(0);
 
         // Load the tasks (if the loading is already
@@ -837,7 +851,10 @@
 
         mContentAlpha = alpha;
         for (int i = getChildCount() - 1; i >= 0; i--) {
-            getChildAt(i).setAlpha(alpha);
+            TaskView child = getPageAt(i);
+            if (!mRunningTaskTileHidden || child.getTask().key.id != mRunningTaskId) {
+                getChildAt(i).setAlpha(alpha);
+            }
         }
 
         int alphaInt = Math.round(alpha * 255);