diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 68dfac72eb..6bc49ed076 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -16,8 +16,6 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW; import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP; import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE; import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME; @@ -52,7 +50,6 @@ import com.android.quickstep.AnimatedFloat; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.RecentsAnimationController; -import com.android.quickstep.SystemUiProxy; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -187,8 +184,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { TaskbarStashController stashController = mControllers.taskbarStashController; stashController.updateStateForFlag(FLAG_IN_APP, !isResumed); stashController.applyState(duration); - SystemUiProxy.INSTANCE.get(mContext).notifyTaskbarStatus(!isResumed, - mControllers.taskbarStashController.isStashedInApp()); } /** @@ -286,11 +281,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override protected void onStashedInAppChanged() { onStashedInAppChanged(mLauncher.getDeviceProfile()); - if (mControllers.taskbarStashController.isStashedInApp()) { - mContext.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_HIDE); - } else { - mContext.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_SHOW); - } } private void onStashedInAppChanged(DeviceProfile deviceProfile) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 0316333a9d..ad0243cb3a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -321,6 +321,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mControllers.taskbarViewController.setRecentsButtonDisabled( mControllers.navbarButtonsViewController.isRecentsDisabled()); mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags); + mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags); } public void onRotationProposal(int rotation, boolean isValid) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java index fc5abd000c..5e76b960fd 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java @@ -45,6 +45,9 @@ public class TaskbarModelCallbacks implements private final TaskbarActivityContext mContext; private final TaskbarView mContainer; + // Initialized in init. + private TaskbarControllers mControllers; + private boolean mBindInProgress = false; public TaskbarModelCallbacks( @@ -53,6 +56,10 @@ public class TaskbarModelCallbacks implements mContainer = container; } + public void init(TaskbarControllers controllers) { + mControllers = controllers; + } + @Override public void startBinding() { mBindInProgress = true; @@ -161,6 +168,7 @@ public class TaskbarModelCallbacks implements int predictionSize = mPredictedItems.size(); int predictionNextIndex = 0; + boolean isHotseatEmpty = true; for (int i = 0; i < hotseatItemInfos.length; i++) { hotseatItemInfos[i] = mHotseatItems.get(i); if (hotseatItemInfos[i] == null && predictionNextIndex < predictionSize) { @@ -168,7 +176,14 @@ public class TaskbarModelCallbacks implements hotseatItemInfos[i].screenId = i; predictionNextIndex++; } + if (hotseatItemInfos[i] != null) { + isHotseatEmpty = false; + } } mContainer.updateHotseatItems(hotseatItemInfos); + + mControllers.taskbarStashController.updateStateForFlag( + TaskbarStashController.FLAG_STASHED_IN_APP_EMPTY, isHotseatEmpty); + mControllers.taskbarStashController.applyState(); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index 02170ab6d2..6d6f0f2e00 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -17,6 +17,10 @@ package com.android.launcher3.taskbar; import static android.view.HapticFeedbackConstants.LONG_PRESS; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -40,8 +44,14 @@ import java.util.function.IntPredicate; public class TaskbarStashController { public static final int FLAG_IN_APP = 1 << 0; - public static final int FLAG_STASHED_IN_APP = 1 << 1; - public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 2; + public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted + public static final int FLAG_STASHED_IN_APP_PINNED = 1 << 2; // app pinning + public static final int FLAG_STASHED_IN_APP_EMPTY = 1 << 3; // no hotseat icons + public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 4; + + // If we're in an app and any of these flags are enabled, taskbar should be stashed. + public static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL + | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY; /** * How long to stash/unstash when manually invoked via long press. @@ -96,8 +106,6 @@ public class TaskbarStashController { private AnimatedFloat mTaskbarStashedHandleAlpha; private AnimatedFloat mTaskbarStashedHandleHintScale; - /** Whether the user has manually invoked taskbar stashing, which we persist. */ - private boolean mIsStashedInApp; /** Whether we are currently visually stashed (might change based on launcher state). */ private boolean mIsStashed = false; private int mState; @@ -107,12 +115,9 @@ public class TaskbarStashController { // Evaluate whether the handle should be stashed private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder( flags -> { - if (!supportsVisualStashing()) { - return false; - } - boolean inApp = (flags & FLAG_IN_APP) != 0; - boolean stashedInApp = (flags & FLAG_STASHED_IN_APP) != 0; - boolean stashedLauncherState = (flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0; + boolean inApp = hasAnyFlag(flags, FLAG_IN_APP); + boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP); + boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE); return (inApp && stashedInApp) || (!inApp && stashedLauncherState); }); @@ -141,12 +146,13 @@ public class TaskbarStashController { mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha(); mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale(); - mIsStashedInApp = supportsManualStashing() + boolean isManuallyStashedInApp = supportsManualStashing() && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF); - updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp); + updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); + applyState(); SystemUiProxy.INSTANCE.get(mActivity) - .notifyTaskbarStatus(/* visible */ true, /* stashed */ mIsStashedInApp); + .notifyTaskbarStatus(/* visible */ false, /* stashed */ isStashedInApp()); } /** @@ -178,10 +184,18 @@ public class TaskbarStashController { } /** - * Returns whether the user has manually stashed the taskbar in apps. + * Returns whether the taskbar should be stashed in apps (e.g. user long pressed to stash). */ public boolean isStashedInApp() { - return mIsStashedInApp; + return hasAnyFlag(FLAGS_STASHED_IN_APP); + } + + private boolean hasAnyFlag(int flagMask) { + return hasAnyFlag(mState, flagMask); + } + + private boolean hasAnyFlag(int flags, int flagMask) { + return (flags & flagMask) != 0; } public int getContentHeight() { @@ -202,7 +216,7 @@ public class TaskbarStashController { // taskbar, we use an OnLongClickListener on TaskbarView instead. return false; } - if (updateAndAnimateIsStashedInApp(false)) { + if (updateAndAnimateIsManuallyStashedInApp(false)) { mControllers.taskbarActivityContext.getDragLayer().performHapticFeedback(LONG_PRESS); return true; } @@ -213,25 +227,32 @@ public class TaskbarStashController { * Updates whether we should stash the taskbar when in apps, and animates to the changed state. * @return Whether we started an animation to either be newly stashed or unstashed. */ - public boolean updateAndAnimateIsStashedInApp(boolean isStashedInApp) { + public boolean updateAndAnimateIsManuallyStashedInApp(boolean isManuallyStashedInApp) { if (!supportsManualStashing()) { return false; } - if (mIsStashedInApp != isStashedInApp) { - mIsStashedInApp = isStashedInApp; - mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, mIsStashedInApp).apply(); - updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp); + if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL) != isManuallyStashedInApp) { + mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, isManuallyStashedInApp).apply(); + updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); applyState(); - - SystemUiProxy.INSTANCE.get(mActivity) - .notifyTaskbarStatus(/* visible */ true, /* stashed */ mIsStashedInApp); - mControllers.uiController.onStashedInAppChanged(); return true; } return false; } private Animator createAnimToIsStashed(boolean isStashed, long duration) { + if (mAnimator != null) { + mAnimator.cancel(); + } + mAnimator = new AnimatorSet(); + + if (!supportsVisualStashing()) { + // Just hide/show the icons instead of stashing into a handle. + mAnimator.play(mIconAlphaForStash.animateToValue(isStashed ? 0 : 1) + .setDuration(duration)); + return mAnimator; + } + AnimatorSet fullLengthAnimatorSet = new AnimatorSet(); // Not exactly half and may overlap. See [first|second]HalfDurationScale below. AnimatorSet firstHalfAnimatorSet = new AnimatorSet(); @@ -287,10 +308,6 @@ public class TaskbarStashController { secondHalfAnimatorSet.setDuration((long) (duration * secondHalfDurationScale)); secondHalfAnimatorSet.setStartDelay((long) (duration * (1 - secondHalfDurationScale))); - if (mAnimator != null) { - mAnimator.cancel(); - } - mAnimator = new AnimatorSet(); mAnimator.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet, secondHalfAnimatorSet); mAnimator.addListener(new AnimatorListenerAdapter() { @@ -360,6 +377,13 @@ public class TaskbarStashController { return mStatePropertyHolder.setState(mState, duration, false); } + /** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */ + public void updateStateForSysuiFlags(int systemUiStateFlags) { + updateStateForFlag(FLAG_STASHED_IN_APP_PINNED, + hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING)); + applyState(); + } + /** * Updates the proper flag to indicate whether the task bar should be stashed. * @@ -377,16 +401,44 @@ public class TaskbarStashController { } } + /** + * Called after updateStateForFlag() and applyState() have been called. + * @param changedFlags The flags that have changed. + */ + private void onStateChangeApplied(int changedFlags) { + if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) { + mControllers.uiController.onStashedInAppChanged(); + } + if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAG_IN_APP)) { + SystemUiProxy.INSTANCE.get(mActivity) + .notifyTaskbarStatus(/* visible */ hasAnyFlag(FLAG_IN_APP), + /* stashed */ isStashedInApp()); + } + if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) { + if (hasAnyFlag(FLAG_STASHED_IN_APP_MANUAL)) { + mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_HIDE); + } else { + mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_SHOW); + } + } + } + private class StatePropertyHolder { private final IntPredicate mStashCondition; private boolean mIsStashed; + private int mPrevFlags; StatePropertyHolder(IntPredicate stashCondition) { mStashCondition = stashCondition; } public Animator setState(int flags, long duration, boolean start) { + if (mPrevFlags != flags) { + int changedFlags = mPrevFlags ^ flags; + onStateChangeApplied(changedFlags); + mPrevFlags = flags; + } boolean isStashed = mStashCondition.test(flags); if (mIsStashed != isStashed) { mIsStashed = isStashed; diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 4cd681428a..ed09fa5984 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -85,6 +85,8 @@ public class TaskbarViewController { mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize; mTaskbarIconScaleForStash.updateValue(1f); + + mModelCallbacks.init(controllers); LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks); } @@ -254,7 +256,8 @@ public class TaskbarViewController { } public View.OnLongClickListener getBackgroundOnLongClickListener() { - return view -> mControllers.taskbarStashController.updateAndAnimateIsStashedInApp(true); + return view -> mControllers.taskbarStashController + .updateAndAnimateIsManuallyStashedInApp(true); } /**