Stash/unstash the task bar based on states

Bug: 193938970
Test: go to any app, stash/unstash, and make sure the states are preserved
Change-Id: I3adf826407e90275687ecea8302abf7a004f1df7
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index acabb0d..b172095 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.taskbar;
 
 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
 import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
 
 import android.animation.Animator;
@@ -162,10 +163,9 @@
         anim.start();
         mIsAnimatingToLauncherViaResume = isResumed;
 
-        if (!isResumed) {
-            TaskbarStashController stashController = mControllers.taskbarStashController;
-            stashController.animateToIsStashed(stashController.isStashedInApp(), duration);
-        }
+        TaskbarStashController stashController = mControllers.taskbarStashController;
+        stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
+        stashController.applyState(duration);
         SystemUiProxy.INSTANCE.get(mContext).notifyTaskbarStatus(!isResumed,
                 mControllers.taskbarStashController.isStashedInApp());
     }
@@ -193,8 +193,11 @@
             public void onAnimationStart(Animator animation) {
                 mTargetStateOverride = toState;
                 mIsAnimatingToLauncherViaGesture = true;
-                // TODO: base this on launcher state
-                stashController.animateToIsStashed(false, duration);
+                // TODO: FLAG_IN_APP might be sufficient for now, but in the future we do want to
+                // add another flag for LauncherState as well. We will need to decide whether to
+                // show hotseat or the task bar.
+                stashController.updateStateForFlag(FLAG_IN_APP, false);
+                stashController.applyState(duration);
             }
         });
 
@@ -327,9 +330,8 @@
                     .start();
 
             TaskbarStashController controller = mControllers.taskbarStashController;
-            if (finishedToApp) {
-                controller.animateToIsStashed(controller.isStashedInApp());
-            }
+            controller.updateStateForFlag(FLAG_IN_APP, finishedToApp);
+            controller.applyState();
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 1f5ff02..fc277cc 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -31,12 +31,17 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.SystemUiProxy;
 
+import java.util.function.IntPredicate;
+
 /**
  * Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
  * create a cohesive animation between stashed/unstashed states.
  */
 public class TaskbarStashController {
 
+    public static final int FLAG_IN_APP = 1 << 0;
+    public static final int FLAG_STASHED_IN_APP = 1 << 1;
+
     /**
      * How long to stash/unstash when manually invoked via long press.
      */
@@ -78,6 +83,9 @@
     private final int mStashedHeight;
     private final int mUnstashedHeight;
 
+    private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
+            flags -> (((flags & FLAG_IN_APP) != 0) && (flags & FLAG_STASHED_IN_APP) != 0));
+
     // Initialized in init.
     private TaskbarControllers mControllers;
     // Taskbar background properties.
@@ -94,6 +102,7 @@
     private boolean mIsStashedInApp;
     /** Whether we are currently visually stashed (might change based on launcher state). */
     private boolean mIsStashed = false;
+    private int mState;
 
     private @Nullable AnimatorSet mAnimator;
 
@@ -124,6 +133,7 @@
 
         mIsStashedInApp = supportsStashing()
                 && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
+        updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp);
 
         SystemUiProxy.INSTANCE.get(mActivity)
                 .notifyTaskbarStatus(/* visible */ true, /* stashed */ mIsStashedInApp);
@@ -190,35 +200,19 @@
             return false;
         }
         if (mIsStashedInApp != isStashedInApp) {
-            boolean wasStashed = mIsStashedInApp;
             mIsStashedInApp = isStashedInApp;
             mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, mIsStashedInApp).apply();
-            boolean isStashed = mIsStashedInApp;
-            if (wasStashed != isStashed) {
-                SystemUiProxy.INSTANCE.get(mActivity)
-                        .notifyTaskbarStatus(/* visible */ true, /* stashed */ isStashed);
-                mControllers.uiController.onStashedInAppChanged();
-                createAnimToIsStashed(isStashed, TASKBAR_STASH_DURATION).start();
-                return true;
-            }
+            updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp);
+            applyState();
+
+            SystemUiProxy.INSTANCE.get(mActivity)
+                    .notifyTaskbarStatus(/* visible */ true, /* stashed */ mIsStashedInApp);
+            mControllers.uiController.onStashedInAppChanged();
+            return true;
         }
         return false;
     }
 
-    /**
-     * Starts an animation to the new stashed state with a default duration.
-     */
-    public void animateToIsStashed(boolean isStashed) {
-        animateToIsStashed(isStashed, TASKBAR_STASH_DURATION);
-    }
-
-    /**
-     * Starts an animation to the new stashed state with the specified duration.
-     */
-    public void animateToIsStashed(boolean isStashed, long duration) {
-        createAnimToIsStashed(isStashed, duration).start();
-    }
-
     private Animator createAnimToIsStashed(boolean isStashed, long duration) {
         AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
         // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
@@ -331,4 +325,47 @@
     private void onIsStashed(boolean isStashed) {
         mControllers.stashedHandleViewController.onIsStashed(isStashed);
     }
+
+    public void applyState() {
+        applyState(TASKBAR_STASH_DURATION);
+    }
+
+    public void applyState(long duration) {
+        mStatePropertyHolder.setState(mState, duration);
+    }
+
+    /**
+     * Updates the proper flag to indicate whether the task bar should be stashed.
+     *
+     * Note that this only updates the flag. {@link #applyState()} needs to be called separately.
+     *
+     * @param flag The flag to update.
+     * @param enabled Whether to enable the flag: True will cause the task bar to be stashed /
+     *                unstashed.
+     */
+    public void updateStateForFlag(int flag, boolean enabled) {
+        if (enabled) {
+            mState |= flag;
+        } else {
+            mState &= ~flag;
+        }
+    }
+
+    private class StatePropertyHolder {
+        private final IntPredicate mStashCondition;
+
+        private boolean mIsStashed;
+
+        StatePropertyHolder(IntPredicate stashCondition) {
+            mStashCondition = stashCondition;
+        }
+
+        public void setState(int flags, long duration) {
+            boolean isStashed = mStashCondition.test(flags);
+            if (mIsStashed != isStashed) {
+                mIsStashed = isStashed;
+                createAnimToIsStashed(mIsStashed, duration).start();
+            }
+        }
+    }
 }