Pipe nav bar transitions logic into task bar

Bug: 349155860
Test: manual
Flag: com.android.wm.shell.enable_taskbar_on_phones
Change-Id: Idaf7ecc7b964a2c406ddf4329b64971b08f5d7de
diff --git a/quickstep/res/drawable-hdpi/nav_background.9.png b/quickstep/res/drawable-hdpi/nav_background.9.png
new file mode 100644
index 0000000..a09e654
--- /dev/null
+++ b/quickstep/res/drawable-hdpi/nav_background.9.png
Binary files differ
diff --git a/quickstep/res/drawable-mdpi/nav_background.9.png b/quickstep/res/drawable-mdpi/nav_background.9.png
new file mode 100644
index 0000000..aa74153
--- /dev/null
+++ b/quickstep/res/drawable-mdpi/nav_background.9.png
Binary files differ
diff --git a/quickstep/res/drawable-xhdpi/nav_background.9.png b/quickstep/res/drawable-xhdpi/nav_background.9.png
new file mode 100644
index 0000000..3b52195
--- /dev/null
+++ b/quickstep/res/drawable-xhdpi/nav_background.9.png
Binary files differ
diff --git a/quickstep/res/drawable-xxhdpi/nav_background.9.png b/quickstep/res/drawable-xxhdpi/nav_background.9.png
new file mode 100644
index 0000000..b35183c
--- /dev/null
+++ b/quickstep/res/drawable-xxhdpi/nav_background.9.png
Binary files differ
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 63e1e01..b647a3e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -41,6 +41,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
@@ -106,6 +107,7 @@
 import com.android.systemui.shared.rotation.FloatingRotationButton;
 import com.android.systemui.shared.rotation.RotationButton;
 import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.systemui.shared.statusbar.phone.BarTransitions;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 
@@ -154,6 +156,8 @@
     public static final int ALPHA_INDEX_SUW = 2;
     private static final int NUM_ALPHA_CHANNELS = 3;
 
+    private static final long AUTODIM_TIMEOUT_MS = 2250;
+
     private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
     private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
     private int mState;
@@ -162,6 +166,7 @@
     private final @Nullable Context mNavigationBarPanelContext;
     private final WindowManagerProxy mWindowManagerProxy;
     private final NearestTouchFrame mNavButtonsView;
+    private final Handler mHandler;
     private final LinearLayout mNavButtonContainer;
     // Used for IME+A11Y buttons
     private final ViewGroup mEndContextualContainer;
@@ -183,7 +188,7 @@
             this::updateNavButtonInAppDisplayProgressForSysui);
     /** Expected nav button dark intensity communicated via the framework. */
     private final AnimatedFloat mTaskbarNavButtonDarkIntensity = new AnimatedFloat(
-            this::updateNavButtonColor);
+            this::onDarkIntensityChanged);
     /** {@code 1} if the Taskbar background color is fully opaque. */
     private final AnimatedFloat mOnTaskbarBackgroundNavButtonColorOverride = new AnimatedFloat(
             this::updateNavButtonColor);
@@ -219,12 +224,19 @@
     private ImageView mRecentsButton;
     private Space mSpace;
 
+    private TaskbarTransitions mTaskbarTransitions;
+    private @BarTransitions.TransitionMode int mTransitionMode;
+
+    private final Runnable mAutoDim = () -> mTaskbarTransitions.setAutoDim(true);
+
     public NavbarButtonsViewController(TaskbarActivityContext context,
-            @Nullable Context navigationBarPanelContext, NearestTouchFrame navButtonsView) {
+            @Nullable Context navigationBarPanelContext, NearestTouchFrame navButtonsView,
+            Handler handler) {
         mContext = context;
         mNavigationBarPanelContext = navigationBarPanelContext;
         mWindowManagerProxy = WindowManagerProxy.INSTANCE.get(mContext);
         mNavButtonsView = navButtonsView;
+        mHandler = handler;
         mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
         mEndContextualContainer = mNavButtonsView.findViewById(R.id.end_contextual_buttons);
         mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
@@ -234,6 +246,8 @@
         mOnBackgroundIconColor = Utilities.isDarkTheme(context)
                 ? context.getColor(R.color.taskbar_nav_icon_light_color)
                 : context.getColor(R.color.taskbar_nav_icon_dark_color);
+
+        mTaskbarTransitions = new TaskbarTransitions(mContext, mNavButtonsView);
     }
 
     /**
@@ -345,6 +359,7 @@
                 R.bool.floating_rotation_button_position_left);
         mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
                 mRotationButtonListener);
+        mTaskbarTransitions.init();
 
         applyState();
         mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
@@ -605,6 +620,39 @@
         mBackButton.setAccessibilityDelegate(accessibilityDelegate);
     }
 
+    public void setWallpaperVisible(boolean isVisible) {
+        mTaskbarTransitions.setWallpaperVisibility(isVisible);
+    }
+
+    public void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
+        mTransitionMode = barMode;
+        if (checkBarModes) {
+            checkNavBarModes();
+        }
+    }
+
+    public void checkNavBarModes() {
+        boolean isBarHidden = (mSysuiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
+        mTaskbarTransitions.transitionTo(mTransitionMode, !isBarHidden);
+    }
+
+    public void finishBarAnimations() {
+        mTaskbarTransitions.finishAnimations();
+    }
+
+    public void touchAutoDim(boolean reset) {
+        mTaskbarTransitions.setAutoDim(false);
+        mHandler.removeCallbacks(mAutoDim);
+        if (reset) {
+            mHandler.postDelayed(mAutoDim, AUTODIM_TIMEOUT_MS);
+        }
+    }
+
+    public void transitionTo(@BarTransitions.TransitionMode int barMode,
+            boolean animate) {
+        mTaskbarTransitions.transitionTo(barMode, animate);
+    }
+
     /** Use to set the translationY for the all nav+contextual buttons */
     public AnimatedFloat getTaskbarNavButtonTranslationY() {
         return mTaskbarNavButtonTranslationY;
@@ -680,8 +728,7 @@
                 mDarkIconColorOnHome);
 
         final int iconColor;
-        if (ENABLE_TASKBAR_NAVBAR_UNIFICATION && enableTaskbarOnPhones()
-                && mContext.isPhoneMode()) {
+        if (ENABLE_TASKBAR_NAVBAR_UNIFICATION && mContext.isPhoneMode()) {
             iconColor = sysUiNavButtonIconColorOnHome;
         } else {
             // Override the color from framework if nav buttons are over an opaque Taskbar surface.
@@ -703,6 +750,11 @@
         }
     }
 
+    private void onDarkIntensityChanged() {
+        updateNavButtonColor();
+        mTaskbarTransitions.onDarkIntensityChanged(mTaskbarNavButtonDarkIntensity.value);
+    }
+
     protected ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
             ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
         return addButton(drawableId, buttonType, parent, navButtonController, id,
@@ -1048,6 +1100,7 @@
                 + mOnBackgroundNavButtonColorOverrideMultiplier.value);
 
         mNavButtonsView.dumpLogs(prefix + "\t", pw);
+        mTaskbarTransitions.dumpLogs(prefix + "\t", pw);
     }
 
     private static String getStateString(int flags) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 5020206..21a8268 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -139,6 +139,7 @@
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.systemui.shared.statusbar.phone.BarTransitions;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
@@ -275,7 +276,8 @@
         mControllers = new TaskbarControllers(this,
                 new TaskbarDragController(this),
                 buttonController,
-                new NavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView),
+                new NavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView,
+                        getMainThreadHandler()),
                 rotationButtonController,
                 new TaskbarDragLayerController(this, mDragLayer),
                 new TaskbarViewController(this, taskbarView),
@@ -799,6 +801,27 @@
         mControllers.taskbarStashController.setSetupUIVisible(isVisible);
     }
 
+    public void setWallpaperVisible(boolean isVisible) {
+        mControllers.navbarButtonsViewController.setWallpaperVisible(isVisible);
+    }
+
+    public void checkNavBarModes() {
+        mControllers.navbarButtonsViewController.checkNavBarModes();
+    }
+
+    public void finishBarAnimations() {
+        mControllers.navbarButtonsViewController.finishBarAnimations();
+    }
+
+    public void touchAutoDim(boolean reset) {
+        mControllers.navbarButtonsViewController.touchAutoDim(reset);
+    }
+
+    public void transitionTo(@BarTransitions.TransitionMode int barMode,
+            boolean animate) {
+        mControllers.navbarButtonsViewController.transitionTo(barMode, animate);
+    }
+
     /**
      * Called when this instance of taskbar is no longer needed
      */
@@ -876,6 +899,9 @@
         mControllers.rotationButtonController.onBehaviorChanged(displayId, behavior);
     }
 
+    public void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
+        mControllers.navbarButtonsViewController.onTransitionModeUpdated(barMode, checkBarModes);
+    }
     public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
         mControllers.navbarButtonsViewController.getTaskbarNavButtonDarkIntensity()
                 .updateValue(darkIntensity);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 051bdc8..b294208 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -72,6 +72,7 @@
 import com.android.quickstep.RecentsActivity;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.AssistUtils;
+import com.android.systemui.shared.statusbar.phone.BarTransitions;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
@@ -519,6 +520,36 @@
         }
     }
 
+    public void setWallpaperVisible(boolean isVisible) {
+        mSharedState.wallpaperVisible = isVisible;
+        if (mTaskbarActivityContext != null) {
+            mTaskbarActivityContext.setWallpaperVisible(isVisible);
+        }
+    }
+
+    public void checkNavBarModes() {
+        if (mTaskbarActivityContext != null) {
+            mTaskbarActivityContext.checkNavBarModes();
+        }
+    }
+
+    public void finishBarAnimations() {
+        if (mTaskbarActivityContext != null) {
+            mTaskbarActivityContext.finishBarAnimations();
+        }
+    }
+
+    public void touchAutoDim(boolean reset) {
+        if (mTaskbarActivityContext != null) {
+            mTaskbarActivityContext.touchAutoDim(reset);
+        }
+    }
+
+    public void transitionTo(@BarTransitions.TransitionMode int barMode,
+            boolean animate) {
+        mTaskbarActivityContext.transitionTo(barMode, animate);
+    }
+
     private boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
         return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent;
     }
@@ -546,6 +577,13 @@
         }
     }
 
+    public void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
+        mSharedState.barMode = barMode;
+        if (mTaskbarActivityContext != null) {
+            mTaskbarActivityContext.onTransitionModeUpdated(barMode, checkBarModes);
+        }
+    }
+
     public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
         mSharedState.navButtonsDarkIntensity = darkIntensity;
         if (mTaskbarActivityContext != null) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
index edaeb63..77bd35f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java
@@ -56,12 +56,17 @@
     // TaskbarManager#onNavButtonsDarkIntensityChanged()
     public float navButtonsDarkIntensity;
 
+    // TaskbarManager#onTransitionModeUpdated()
+    public int barMode;
+
     // TaskbarManager#onNavigationBarLumaSamplingEnabled()
     public int mLumaSamplingDisplayId = DEFAULT_DISPLAY;
     public boolean mIsLumaSamplingEnabled = true;
 
     public boolean setupUIVisible = false;
 
+    public boolean wallpaperVisible = false;
+
     public boolean allAppsVisible = false;
 
     // LauncherTaskbarUIController#mTaskbarInAppDisplayProgressMultiProp
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTransitions.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTransitions.java
new file mode 100644
index 0000000..615db01
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTransitions.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 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.launcher3.taskbar;
+
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.taskbar.navbutton.NearestTouchFrame;
+import com.android.systemui.shared.statusbar.phone.BarTransitions;
+
+import java.io.PrintWriter;
+
+/** Manages task bar transitions */
+public class TaskbarTransitions extends BarTransitions implements
+        TaskbarControllers.LoggableTaskbarController {
+
+    private final TaskbarActivityContext mContext;
+
+    private boolean mWallpaperVisible;
+
+    private boolean mLightsOut;
+    private boolean mAutoDim;
+    private View mNavButtons;
+    private float mDarkIntensity;
+
+    private final NearestTouchFrame mView;
+
+    public TaskbarTransitions(TaskbarActivityContext context, NearestTouchFrame view) {
+        super(view, R.drawable.nav_background);
+
+        mContext = context;
+        mView = view;
+    }
+
+    void init() {
+        mView.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    mNavButtons = mView.findViewById(R.id.end_nav_buttons);
+                    applyLightsOut(false, true);
+                });
+        mNavButtons = mView.findViewById(R.id.end_nav_buttons);
+
+        applyModeBackground(-1, getMode(), false /*animate*/);
+        applyLightsOut(false /*animate*/, true /*force*/);
+        if (mContext.isPhoneButtonNavMode()) {
+            mBarBackground.setOverrideAlpha(1);
+        }
+    }
+
+    void setWallpaperVisibility(boolean visible) {
+        mWallpaperVisible = visible;
+        applyLightsOut(true, false);
+    }
+
+    @Override
+    public void setAutoDim(boolean autoDim) {
+        // Ensure we aren't in gestural nav if we are triggering auto dim
+        if (autoDim && !mContext.isPhoneButtonNavMode()) {
+            return;
+        }
+        if (mAutoDim == autoDim) return;
+        mAutoDim = autoDim;
+        applyLightsOut(true, false);
+    }
+
+    @Override
+    protected void onTransition(int oldMode, int newMode, boolean animate) {
+        super.onTransition(oldMode, newMode, animate);
+        applyLightsOut(animate, false /*force*/);
+    }
+
+    private void applyLightsOut(boolean animate, boolean force) {
+        // apply to lights out
+        applyLightsOut(isLightsOut(getMode()), animate, force);
+    }
+
+    private void applyLightsOut(boolean lightsOut, boolean animate, boolean force) {
+        if (!force && lightsOut == mLightsOut) return;
+
+        mLightsOut = lightsOut;
+        if (mNavButtons == null) return;
+
+        // ok, everyone, stop it right there
+        mNavButtons.animate().cancel();
+
+        // Bump percentage by 10% if dark.
+        float darkBump = mDarkIntensity / 10;
+        final float navButtonsAlpha = lightsOut ? 0.6f + darkBump : 1f;
+
+        if (!animate) {
+            mNavButtons.setAlpha(navButtonsAlpha);
+        } else {
+            final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION;
+            mNavButtons.animate()
+                    .alpha(navButtonsAlpha)
+                    .setDuration(duration)
+                    .start();
+        }
+    }
+
+    void onDarkIntensityChanged(float darkIntensity) {
+        mDarkIntensity = darkIntensity;
+        if (mAutoDim) {
+            applyLightsOut(false, true);
+        }
+    }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarTransitions:");
+
+        pw.println(prefix + "\tmMode=" + getMode());
+        pw.println(prefix + "\tmAlwaysOpaque: " + isAlwaysOpaque());
+        pw.println(prefix + "\tmWallpaperVisible: " + mWallpaperVisible);
+        pw.println(prefix + "\tmLightsOut: " + mLightsOut);
+        pw.println(prefix + "\tmAutoDim: " + mAutoDim);
+        pw.println(prefix + "\tbg overrideAlpha: " + mBarBackground.getOverrideAlpha());
+        pw.println(prefix + "\tbg color: " + mBarBackground.getColor());
+        pw.println(prefix + "\tbg frame: " + mBarBackground.getFrame());
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index bfdc3df..ee93cd6 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -70,6 +70,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.util.ArraySet;
@@ -126,6 +127,7 @@
 import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
+import com.android.systemui.shared.statusbar.phone.BarTransitions;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
 import com.android.systemui.shared.system.InputConsumerController;
@@ -330,6 +332,49 @@
             });
         }
 
+        @BinderThread
+        @Override
+        public void updateWallpaperVisibility(int displayId, boolean visible) {
+            MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis ->
+                    executeForTaskbarManager(
+                            taskbarManager -> taskbarManager.setWallpaperVisible(visible))
+            ));
+        }
+
+        @BinderThread
+        @Override
+        public void checkNavBarModes() {
+            MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis ->
+                    executeForTaskbarManager(TaskbarManager::checkNavBarModes)
+            ));
+        }
+
+        @BinderThread
+        @Override
+        public void finishBarAnimations() {
+            MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis ->
+                    executeForTaskbarManager(TaskbarManager::finishBarAnimations)
+            ));
+        }
+
+        @BinderThread
+        @Override
+        public void touchAutoDim(boolean reset) {
+            MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis ->
+                    executeForTaskbarManager(taskbarManager -> taskbarManager.touchAutoDim(reset))
+            ));
+        }
+
+        @BinderThread
+        @Override
+        public void transitionTo(@BarTransitions.TransitionMode int barMode,
+                boolean animate) {
+            MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis ->
+                    executeForTaskbarManager(
+                            taskbarManager -> taskbarManager.transitionTo(barMode, animate))
+            ));
+        }
+
         /**
          * Preloads the Overview activity.
          * <p>
@@ -359,6 +404,12 @@
         }
 
         @Override
+        public void onTransitionModeUpdated(int barMode, boolean checkBarModes) {
+            executeForTaskbarManager(taskbarManager ->
+                    taskbarManager.onTransitionModeUpdated(barMode, checkBarModes));
+        }
+
+        @Override
         public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
             executeForTaskbarManager(taskbarManager ->
                     taskbarManager.onNavButtonsDarkIntensityChanged(darkIntensity));