diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java index 941b4b077a..c4255bf70f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java @@ -49,7 +49,8 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT public static final int ALPHA_INDEX_STASHED = 0; public static final int ALPHA_INDEX_HOME_DISABLED = 1; public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 2; - private static final int NUM_ALPHA_CHANNELS = 3; + public static final int ALPHA_INDEX_HIDDEN_WHILE_DREAMING = 3; + private static final int NUM_ALPHA_CHANNELS = 4; /** * The SharedPreferences key for whether the stashed handle region is dark. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index 2628a7f17d..2fba37ebbd 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -53,6 +53,10 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa // Translation property for taskbar background. private final AnimatedFloat mBgOffset = new AnimatedFloat(this::updateBackgroundOffset); + // Used to fade in/out the entirety of the taskbar, for a smooth transition before/after sysui + // changes the inset visibility. + private final AnimatedFloat mTaskbarAlpha = new AnimatedFloat(this::updateTaskbarAlpha); + // Initialized in init. private TaskbarControllers mControllers; private TaskbarStashViaTouchController mTaskbarStashViaTouchController; @@ -83,6 +87,9 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa mAssistantBgTaskbar.value = 1; mBgOverride.value = 1; updateBackgroundAlpha(); + + mTaskbarAlpha.value = 1; + updateTaskbarAlpha(); } public void onDestroy() { @@ -127,6 +134,10 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa return mBgOffset; } + public AnimatedFloat getTaskbarAlpha() { + return mTaskbarAlpha; + } + /** * Make updates when configuration changes. */ @@ -165,6 +176,10 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa updateOnBackgroundNavButtonColorIntensity(); } + private void updateTaskbarAlpha() { + mTaskbarDragLayer.setAlpha(mTaskbarAlpha.value); + } + @Override public void setCornerRoundness(float cornerRoundness) { mTaskbarDragLayer.setCornerRoundness(cornerRoundness); @@ -188,6 +203,7 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa pw.println(prefix + "TaskbarDragLayerController:"); pw.println(prefix + "\tmBgOffset=" + mBgOffset.value); + pw.println(prefix + "\tmTaskbarAlpha=" + mTaskbarAlpha.value); pw.println(prefix + "\tmFolderMargin=" + mFolderMargin); pw.println(prefix + "\tmLastSetBackgroundAlpha=" + mLastSetBackgroundAlpha); pw.println(prefix + "\t\tmBgOverride=" + mBgOverride.value); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index b98ea81fcc..9bc8cdd44b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -23,11 +23,15 @@ import static com.android.launcher3.util.FlagDebugUtils.appendFlag; import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange; import static com.android.systemui.animation.Interpolators.EMPHASIZED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_AWAKE; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK; +import static com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_AWAKE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.os.SystemClock; import android.util.Log; import androidx.annotation.NonNull; @@ -93,9 +97,25 @@ public class TaskbarLauncherStateController { */ private static final int FLAG_LAUNCHER_WAS_ACTIVE_WHILE_AWAKE = 1 << 4; - /** Whether the device is currently locked. */ + /** + * Whether the device is currently locked. + * + */ private static final int FLAG_DEVICE_LOCKED = 1 << 5; + /** + * Whether the complete taskbar is completely hidden (neither visible stashed or unstashed). + * This is tracked to allow a nice transition of the taskbar before SysUI forces it away by + * hiding the inset. + * + * This flag is predominanlty set while FLAG_DEVICE_LOCKED is set, thus the taskbar's invisible + * resting state while hidden is stashed. + */ + private static final int FLAG_TASKBAR_HIDDEN = 1 << 6; + private static final int FLAGS_LAUNCHER_ACTIVE = FLAG_RESUMED | FLAG_TRANSITION_TO_RESUMED; /** Equivalent to an int with all 1s for binary operation purposes */ private static final int FLAGS_ALL = ~0; @@ -104,11 +124,21 @@ public class TaskbarLauncherStateController { private static final float TASKBAR_BG_ALPHA_NOT_LAUNCHER_NOT_ALIGNED_DELAY_MULT = 0.33f; private static final float TASKBAR_BG_ALPHA_LAUNCHER_IS_ALIGNED_DURATION_MULT = 0.25f; + /** + * Delay for the taskbar fade-in. + * + * Helps to avoid visual noise when unlocking successfully via SFPS, and the device transitions + * to launcher directly. The delay avoids the navbar to become briefly visible. The duration + * is the same as in SysUI, see http://shortn/_uNSbDoRUSr. + */ + private static final long TASKBAR_SHOW_DELAY_MS = 250; + private final AnimatedFloat mIconAlignment = new AnimatedFloat(this::onIconAlignmentRatioChanged); private TaskbarControllers mControllers; private AnimatedFloat mTaskbarBackgroundAlpha; + private AnimatedFloat mTaskbarAlpha; private AnimatedFloat mTaskbarCornerRoundness; private MultiProperty mIconAlphaForHome; private QuickstepLauncher mLauncher; @@ -117,6 +147,9 @@ public class TaskbarLauncherStateController { private int mState; private LauncherState mLauncherState = LauncherState.NORMAL; + // Time when FLAG_TASKBAR_HIDDEN was last cleared, SystemClock.elapsedRealtime (milliseconds). + private long mLastUnlockTimeMs = 0; + private @Nullable TaskBarRecentsAnimationListener mTaskBarRecentsAnimationListener; private boolean mIsAnimatingToLauncher; @@ -187,6 +220,7 @@ public class TaskbarLauncherStateController { mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController .getTaskbarBackgroundAlpha(); + mTaskbarAlpha = mControllers.taskbarDragLayerController.getTaskbarAlpha(); mTaskbarCornerRoundness = mControllers.getTaskbarCornerRoundness(); mIconAlphaForHome = mControllers.taskbarViewController .getTaskbarIconAlpha().get(ALPHA_INDEX_HOME); @@ -279,6 +313,15 @@ public class TaskbarLauncherStateController { boolean isDeviceLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED); updateStateForFlag(FLAG_DEVICE_LOCKED, isDeviceLocked); + // Taskbar is hidden whenever the device is dreaming. The dreaming state includes the + // interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in + // when the device is asleep, the second condition extends ensures that the transition from + // and to the WAKEFULNESS_ASLEEP state also hide the taskbar, and improves the taskbar + // hide/reveal animation timings. + boolean isTaskbarHidden = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_DEVICE_DREAMING) + || (systemUiStateFlags & SYSUI_STATE_WAKEFULNESS_MASK) != WAKEFULNESS_AWAKE; + updateStateForFlag(FLAG_TASKBAR_HIDDEN, isTaskbarHidden); + if (skipAnim) { applyState(0); } else { @@ -406,6 +449,41 @@ public class TaskbarLauncherStateController { AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext); } + if (hasAnyFlag(changedFlags, FLAG_TASKBAR_HIDDEN) && !hasAnyFlag(FLAG_TASKBAR_HIDDEN)) { + // Take note of the current time, as the taskbar is made visible again. + mLastUnlockTimeMs = SystemClock.elapsedRealtime(); + } + + boolean isHidden = hasAnyFlag(FLAG_TASKBAR_HIDDEN); + float taskbarAlpha = isHidden ? 0 : 1; + if (mTaskbarAlpha.isAnimating() || mTaskbarAlpha.value != taskbarAlpha) { + Animator taskbarVisibility = mTaskbarAlpha.animateToValue(taskbarAlpha); + + taskbarVisibility.setDuration(duration); + if (isHidden) { + // Stash the transient taskbar once the taskbar is not visible. This reduces + // visual noise when unlocking the device afterwards. + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + TaskbarStashController stashController = + mControllers.taskbarStashController; + stashController.updateAndAnimateTransientTaskbar( + /* stash */ true, /* duration */ 0); + } + }); + } else { + // delay the fade in animation a bit to reduce visual noise when waking up a device + // with a fingerprint reader. This should only be done when the device was woken + // up via fingerprint reader, however since this information is currently not + // available, opting to always delay the fade-in a bit. + long durationSinceLastUnlockMs = SystemClock.elapsedRealtime() - mLastUnlockTimeMs; + taskbarVisibility.setStartDelay( + Math.max(0, TASKBAR_SHOW_DELAY_MS - durationSinceLastUnlockMs)); + } + animatorSet.play(taskbarVisibility); + } + float backgroundAlpha = isInLauncher && isTaskbarAlignedWithHotseat() ? 0 : 1; // Don't animate if background has reached desired value. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 92cac7d090..5f117402fb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -505,9 +505,16 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba } /** - * Stash or unstashes the transient taskbar. + * Stash or unstashes the transient taskbar, using the default TASKBAR_STASH_DURATION. */ public void updateAndAnimateTransientTaskbar(boolean stash) { + updateAndAnimateTransientTaskbar(stash, TASKBAR_STASH_DURATION); + } + + /** + * Stash or unstashes the transient taskbar. + */ + public void updateAndAnimateTransientTaskbar(boolean stash, long duration) { if (!DisplayController.isTransientTaskbar(mActivity)) { return; } @@ -945,16 +952,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING)); boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED); - boolean wasLocked = hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED); updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked); - if (isLocked && !wasLocked && DisplayController.isTransientTaskbar(mActivity)) { - // Stash the transient taskbar when locking the device. This improves the transition - // to AoD (otherwise the taskbar stays a bit too long above the collapsing AoD scrim), - // and ensures the taskar state is reset when unlocking the device afterwards. - updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, true); - } - // Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress. mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING); mIsImeSwitcherShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SWITCHER_SHOWING);