Merge "Updated overview exit animation for 3 button navigation" into tm-qpr-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index c85e71c..765d36c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -258,7 +258,7 @@
<dimen name="taskbar_contextual_button_padding">16dp</dimen>
<dimen name="taskbar_contextual_padding_top">8dp</dimen>
<dimen name="taskbar_nav_buttons_size">44dp</dimen>
- <dimen name="taskbar_contextual_button_margin">47dp</dimen>
+ <dimen name="taskbar_contextual_button_margin">48dp</dimen>
<dimen name="taskbar_hotseat_nav_spacing">24dp</dimen>
<dimen name="taskbar_contextual_buttons_size">35dp</dimen>
<dimen name="taskbar_stashed_size">24dp</dimen>
@@ -268,6 +268,7 @@
<dimen name="taskbar_stashed_handle_height">4dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y">25dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y_return_overshoot">4dp</dimen>
+ <dimen name="taskbar_edu_horizontal_margin">112dp</dimen>
<dimen name="taskbar_nav_buttons_width_kids">88dp</dimen>
<dimen name="taskbar_nav_buttons_height_kids">40dp</dimen>
<dimen name="taskbar_nav_buttons_corner_radius_kids">40dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index a219ac6..5178968 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -38,6 +38,7 @@
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfo;
@@ -116,7 +117,8 @@
@Override
protected boolean isTaskbarTouchable() {
- return !mTaskbarLauncherStateController.isAnimatingToLauncher();
+ return !(mTaskbarLauncherStateController.isAnimatingToLauncher()
+ && mTaskbarLauncherStateController.goingToAlignedLauncherState());
}
public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
@@ -291,9 +293,14 @@
@Override
public void setSystemGestureInProgress(boolean inProgress) {
super.setSystemGestureInProgress(inProgress);
- // Launcher's ScrimView will draw the background throughout the gesture. But once the
- // gesture ends, start drawing taskbar's background again since launcher might stop drawing.
- forceHideBackground(inProgress);
+ // TODO(b/250645563): Don't show round corners when leaving in-app state, and remove
+ // forceHideBackground call entirely.
+ if (!FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
+ // Launcher's ScrimView will draw the background throughout the gesture. But once the
+ // gesture ends, start drawing taskbar's background again since launcher might stop
+ // drawing.
+ forceHideBackground(inProgress);
+ }
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index a90af04..725ce11 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -116,12 +116,18 @@
private static final int FLAG_SCREEN_PINNING_ACTIVE = 1 << 11;
private static final int FLAG_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 12;
private static final int FLAG_SMALL_SCREEN = 1 << 13;
+ private static final int FLAG_SLIDE_IN_VIEW_VISIBLE = 1 << 14;
+
+ /** Flags where a UI could be over a slide in view, so the color override should be disabled. */
+ private static final int FLAGS_SLIDE_IN_VIEW_ICON_COLOR_OVERRIDE_DISABLED =
+ FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_VOICE_INTERACTION_WINDOW_SHOWING;
private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
public static final int ALPHA_INDEX_IMMERSIVE_MODE = 0;
public static final int ALPHA_INDEX_KEYGUARD_OR_DISABLE = 1;
- private static final int NUM_ALPHA_CHANNELS = 2;
+ public static final int ALPHA_INDEX_SUW = 2;
+ private static final int NUM_ALPHA_CHANNELS = 3;
private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
@@ -135,6 +141,8 @@
private final ViewGroup mStartContextualContainer;
private final int mLightIconColor;
private final int mDarkIconColor;
+ /** Color to use for navigation bar buttons, if a slide in view is visible. */
+ private final int mSlideInViewIconColor;
private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
this::updateNavButtonTranslationY);
@@ -149,6 +157,9 @@
this::updateNavButtonDarkIntensity);
private final AnimatedFloat mNavButtonDarkIntensityMultiplier = new AnimatedFloat(
this::updateNavButtonDarkIntensity);
+ /** Overrides the navigation button color to {@code mSlideInViewIconColor} when {@code 1}. */
+ private final AnimatedFloat mSlideInViewNavButtonColorOverride = new AnimatedFloat(
+ this::updateNavButtonDarkIntensity);
private final RotationButtonListener mRotationButtonListener = new RotationButtonListener();
private final Rect mFloatingRotationButtonBounds = new Rect();
@@ -180,6 +191,8 @@
mLightIconColor = context.getColor(R.color.taskbar_nav_icon_light_color);
mDarkIconColor = context.getColor(R.color.taskbar_nav_icon_dark_color);
+ // Can precompute color since dark theme change recreates taskbar.
+ mSlideInViewIconColor = Utilities.isDarkTheme(context) ? mLightIconColor : mDarkIconColor;
}
/**
@@ -243,6 +256,11 @@
flags -> (flags & FLAG_IME_VISIBLE) != 0 && !isInKidsMode, AnimatedFloat.VALUE,
transForIme, defaultButtonTransY));
+ mPropertyHolders.add(new StatePropertyHolder(
+ mSlideInViewNavButtonColorOverride,
+ flags -> ((flags & FLAG_SLIDE_IN_VIEW_VISIBLE) != 0)
+ && ((flags & FLAGS_SLIDE_IN_VIEW_ICON_COLOR_OVERRIDE_DISABLED) == 0)));
+
if (alwaysShowButtons) {
initButtons(mNavButtonContainer, mEndContextualContainer,
mControllers.navButtonController);
@@ -253,11 +271,17 @@
// end-aligned, so start-align instead.
FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
mNavButtonContainer.getLayoutParams();
- navButtonsLayoutParams.setMarginStart(navButtonsLayoutParams.getMarginEnd());
+ navButtonsLayoutParams.setMarginStart(
+ resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin));
navButtonsLayoutParams.setMarginEnd(0);
navButtonsLayoutParams.gravity = Gravity.START;
mNavButtonContainer.requestLayout();
+ // Hide back button in SUW if keyboard is showing (IME draws its own back).
+ mPropertyHolders.add(new StatePropertyHolder(
+ mBackButtonAlpha.getProperty(ALPHA_INDEX_SUW),
+ flags -> (flags & FLAG_IME_VISIBLE) == 0));
+
// TODO(b/210906568) Dark intensity is currently not propagated during setup, so set
// it based on dark theme for now.
int mode = resources.getConfiguration().uiMode
@@ -524,6 +548,12 @@
applyState();
}
+ /** {@code true} if a slide in view is currently visible over taskbar. */
+ public void setSlideInViewVisible(boolean isSlideInViewVisible) {
+ updateStateForFlag(FLAG_SLIDE_IN_VIEW_VISIBLE, isSlideInViewVisible);
+ applyState();
+ }
+
/**
* Returns true if IME bar is visible
*/
@@ -669,8 +699,11 @@
private void updateNavButtonDarkIntensity() {
float darkIntensity = mTaskbarNavButtonDarkIntensity.value
* mNavButtonDarkIntensityMultiplier.value;
- int iconColor = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, mLightIconColor,
- mDarkIconColor);
+ ArgbEvaluator argbEvaluator = ArgbEvaluator.getInstance();
+ int iconColor = (int) argbEvaluator.evaluate(
+ darkIntensity, mLightIconColor, mDarkIconColor);
+ iconColor = (int) argbEvaluator.evaluate(
+ mSlideInViewNavButtonColorOverride.value, iconColor, mSlideInViewIconColor);
for (ImageView button : mAllButtons) {
button.setImageTintList(ColorStateList.valueOf(iconColor));
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 2b80b75..707023b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -165,6 +165,7 @@
* Cleans up all controllers.
*/
public void onDestroy() {
+ mAreAllControllersInitialized = false;
mSharedState = null;
navbarButtonsViewController.onDestroy();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
index 32a3c10..95b93fe 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
@@ -90,6 +90,9 @@
mTaskbarEduView = (TaskbarEduView) mActivity.getLayoutInflater().inflate(
R.layout.taskbar_edu, mActivity.getDragLayer(), false);
mTaskbarEduView.init(new TaskbarEduCallbacks());
+ mControllers.navbarButtonsViewController.setSlideInViewVisible(true);
+ mTaskbarEduView.setOnCloseBeginListener(
+ () -> mControllers.navbarButtonsViewController.setSlideInViewVisible(false));
mTaskbarEduView.addOnCloseListener(() -> mTaskbarEduView = null);
mTaskbarEduView.show();
startAnim(createWaveAnim());
@@ -217,5 +220,9 @@
v -> mTaskbarEduView.snapToPage(currentPage + 1));
}
}
+
+ int getIconLayoutBoundsWidth() {
+ return mControllers.taskbarViewController.getIconLayoutBounds().width();
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
index 89d67be..c0cbbd6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
@@ -39,6 +39,9 @@
private final Rect mInsets = new Rect();
+ // Initialized in init.
+ private TaskbarEduController.TaskbarEduCallbacks mTaskbarEduCallbacks;
+
private Button mStartButton;
private Button mEndButton;
private TaskbarEduPagedView mPagedView;
@@ -56,6 +59,7 @@
if (mPagedView != null) {
mPagedView.setControllerCallbacks(callbacks);
}
+ mTaskbarEduCallbacks = callbacks;
}
@Override
@@ -101,6 +105,22 @@
Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0);
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int contentWidth = Math.min(getContentAreaWidth(), getMeasuredWidth());
+ contentWidth = Math.max(contentWidth, mTaskbarEduCallbacks.getIconLayoutBoundsWidth());
+ int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY);
+
+ mContent.measure(contentAreaWidthSpec, MeasureSpec.UNSPECIFIED);
+ }
+
+ private int getContentAreaWidth() {
+ return mTaskbarEduCallbacks.getIconLayoutBoundsWidth()
+ + getResources().getDimensionPixelSize(R.dimen.taskbar_edu_horizontal_margin) * 2;
+ }
+
/** Show the Education flow. */
public void show() {
attachToContainer();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 58c689b..de37b70 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -50,7 +50,6 @@
import java.util.HashMap;
import java.util.StringJoiner;
import java.util.function.Consumer;
-import java.util.function.Supplier;
/**
* Track LauncherState, RecentsAnimation, resumed state for task bar in one place here and animate
@@ -65,15 +64,12 @@
public static final int FLAG_RECENTS_ANIMATION_RUNNING = 1 << 1;
public static final int FLAG_TRANSITION_STATE_RUNNING = 1 << 2;
+ private static final int FLAGS_LAUNCHER = FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING;
/** Equivalent to an int with all 1s for binary operation purposes */
private static final int FLAGS_ALL = ~0;
- private final AnimatedFloat mIconAlignmentForResumedState =
- new AnimatedFloat(this::onIconAlignmentRatioChangedForAppAndHomeTransition);
- private final AnimatedFloat mIconAlignmentForGestureState =
- new AnimatedFloat(this::onIconAlignmentRatioChangedForAppAndHomeTransition);
- private final AnimatedFloat mIconAlignmentForLauncherState =
- new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);
+ private final AnimatedFloat mIconAlignment =
+ new AnimatedFloat(this::onIconAlignmentRatioChanged);
private TaskbarControllers mControllers;
private AnimatedFloat mTaskbarBackgroundAlpha;
@@ -86,8 +82,7 @@
private @Nullable TaskBarRecentsAnimationListener mTaskBarRecentsAnimationListener;
- private boolean mIsAnimatingToLauncherViaGesture;
- private boolean mIsAnimatingToLauncherViaResume;
+ private boolean mIsAnimatingToLauncher;
private boolean mShouldDelayLauncherStateAnim;
@@ -148,8 +143,8 @@
mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
mIconAlphaForHome.setConsumer(mIconAlphaForHomeConsumer);
- mIconAlignmentForResumedState.finishAnimation();
- onIconAlignmentRatioChangedForAppAndHomeTransition();
+ mIconAlignment.finishAnimation();
+ onIconAlignmentRatioChanged();
mLauncher.getStateManager().addStateListener(mStateListener);
@@ -165,9 +160,7 @@
public void onDestroy() {
mCanSyncViews = false;
- mIconAlignmentForResumedState.finishAnimation();
- mIconAlignmentForGestureState.finishAnimation();
- mIconAlignmentForLauncherState.finishAnimation();
+ mIconAlignment.finishAnimation();
mIconAlphaForHome.setConsumer(null);
mLauncher.getHotseat().setIconsAlpha(1f);
@@ -187,6 +180,9 @@
TaskbarStashController stashController = mControllers.taskbarStashController;
stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
toState.isTaskbarStashed(mLauncher));
+ if (DEBUG) {
+ Log.d(TAG, "createAnimToLauncher - FLAG_IN_APP: " + false);
+ }
stashController.updateStateForFlag(FLAG_IN_APP, false);
updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, true);
@@ -201,7 +197,7 @@
}
public boolean isAnimatingToLauncher() {
- return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
+ return mIsAnimatingToLauncher;
}
public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
@@ -261,11 +257,29 @@
}
private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
+ boolean goingToLauncher = isInLauncher();
+ final float toAlignment;
+ if (goingToLauncher) {
+ boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
+ boolean willStashVisually = isInStashedState
+ && mControllers.taskbarStashController.supportsVisualStashing();
+ boolean isTaskbarAlignedWithHotseat =
+ mLauncherState.isTaskbarAlignedWithHotseat(mLauncher);
+ toAlignment = isTaskbarAlignedWithHotseat && !willStashVisually ? 1 : 0;
+ } else {
+ toAlignment = 0;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "onStateChangeApplied - mState: " + getStateString(mState)
+ + ", changedFlags: " + getStateString(changedFlags)
+ + ", goingToLauncher: " + goingToLauncher
+ + ", mLauncherState: " + mLauncherState
+ + ", toAlignment: " + toAlignment);
+ }
AnimatorSet animatorSet = new AnimatorSet();
// Add the state animation first to ensure FLAG_IN_STASHED_LAUNCHER_STATE is set and we can
// determine whether goingToUnstashedLauncherStateChanged.
- boolean wasGoingToUnstashedLauncherState = goingToUnstashedLauncherState();
if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) {
boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING);
playStateTransitionAnim(animatorSet, duration, committed);
@@ -276,95 +290,69 @@
applyState(0 /* duration */);
}
}
- boolean goingToUnstashedLauncherStateChanged = wasGoingToUnstashedLauncherState
- != goingToUnstashedLauncherState();
- boolean launcherStateChangedDuringAnimToResumeAlignment =
- mIconAlignmentForResumedState.isAnimating() && goingToUnstashedLauncherStateChanged;
- if (hasAnyFlag(changedFlags, FLAG_RESUMED)
- || launcherStateChangedDuringAnimToResumeAlignment) {
- boolean isResumed = isResumed();
- // If launcher is resumed, we show the icons when going to an unstashed launcher state
- // or launcher state is not changed (e.g. in overview, launcher is paused and resumed).
- float toAlignmentForResumedState = isResumed && (goingToUnstashedLauncherState()
- || !goingToUnstashedLauncherStateChanged) ? 1 : 0;
- // If we're already animating to the value, just leave it be instead of restarting it.
- if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) {
- ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState
- .animateToValue(toAlignmentForResumedState)
- .setDuration(duration);
- if (DEBUG) {
- Log.d(TAG, "mIconAlignmentForResumedState - "
- + mIconAlignmentForResumedState.value
- + " -> " + toAlignmentForResumedState + ": " + duration);
+ if (hasAnyFlag(changedFlags, FLAGS_LAUNCHER)) {
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mIsAnimatingToLauncher = false;
}
- resumeAlignAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mIsAnimatingToLauncherViaResume = false;
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mIsAnimatingToLauncher = goingToLauncher;
+
+ TaskbarStashController stashController =
+ mControllers.taskbarStashController;
+ if (DEBUG) {
+ Log.d(TAG, "onAnimationStart - FLAG_IN_APP: " + !goingToLauncher);
}
-
- @Override
- public void onAnimationStart(Animator animation) {
- mIsAnimatingToLauncherViaResume = isResumed;
-
- TaskbarStashController stashController =
- mControllers.taskbarStashController;
- stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
- stashController.applyState(duration);
- }
- });
- animatorSet.play(resumeAlignAnim);
- }
- }
-
-
- boolean launcherStateChangedDuringAnimToGestureAlignment =
- mIconAlignmentForGestureState.isAnimating() && goingToUnstashedLauncherStateChanged;
- if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)
- || launcherStateChangedDuringAnimToGestureAlignment) {
- boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
- float toAlignmentForGestureState = isRecentsAnimationRunning
- && goingToUnstashedLauncherState() ? 1 : 0;
- // If we're already animating to the value, just leave it be instead of restarting it.
- if (!mIconAlignmentForGestureState.isAnimatingToValue(toAlignmentForGestureState)) {
- Animator gestureAlignAnim = mIconAlignmentForGestureState
- .animateToValue(toAlignmentForGestureState);
- if (isRecentsAnimationRunning) {
- gestureAlignAnim.setDuration(duration);
+ stashController.updateStateForFlag(FLAG_IN_APP, !goingToLauncher);
+ stashController.applyState(duration);
}
- if (DEBUG) {
- Log.d(TAG, "mIconAlignmentForGestureState - "
- + mIconAlignmentForGestureState.value
- + " -> " + toAlignmentForGestureState + ": " + duration);
- }
- gestureAlignAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mIsAnimatingToLauncherViaGesture = false;
- }
+ });
- @Override
- public void onAnimationStart(Animator animation) {
- mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
- }
- });
- animatorSet.play(gestureAlignAnim);
- }
- }
-
- if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
- boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
if (goingToLauncher) {
// Handle closing open popups when going home/overview
AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
}
- animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
+ }
+
+ float backgroundAlpha =
+ goingToLauncher && mLauncherState.isTaskbarAlignedWithHotseat(mLauncher)
+ ? 0 : 1;
+ // Don't animate if background has reached desired value.
+ if (mTaskbarBackgroundAlpha.isAnimating()
+ || mTaskbarBackgroundAlpha.value != backgroundAlpha) {
+ mTaskbarBackgroundAlpha.cancelAnimation();
+ if (DEBUG) {
+ Log.d(TAG, "onStateChangeApplied - taskbarBackgroundAlpha - "
+ + mTaskbarBackgroundAlpha.value
+ + " -> " + backgroundAlpha + ": " + duration);
+ }
+ animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(backgroundAlpha)
.setDuration(duration));
}
+ if (mIconAlignment.isAnimatingToValue(toAlignment)
+ || mIconAlignment.isSettledOnValue(toAlignment)) {
+ // Already at desired value, but make sure we run the callback at the end.
+ animatorSet.addListener(AnimatorListeners.forEndCallback(
+ this::onIconAlignmentRatioChanged));
+ } else {
+ mIconAlignment.cancelAnimation();
+ ObjectAnimator iconAlignAnim = mIconAlignment
+ .animateToValue(toAlignment)
+ .setDuration(duration);
+ if (DEBUG) {
+ Log.d(TAG, "onStateChangeApplied - iconAlignment - "
+ + mIconAlignment.value
+ + " -> " + toAlignment + ": " + duration);
+ }
+ animatorSet.play(iconAlignAnim);
+ }
animatorSet.setInterpolator(EMPHASIZED);
+
if (start) {
animatorSet.start();
}
@@ -372,18 +360,13 @@
}
/** Returns whether we're going to a state where taskbar icons should align with launcher. */
- private boolean goingToUnstashedLauncherState() {
- return !mControllers.taskbarStashController.isInStashedLauncherState();
+ public boolean goingToAlignedLauncherState() {
+ return mLauncherState.isTaskbarAlignedWithHotseat(mLauncher);
}
private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
boolean committed) {
boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
- boolean willStashVisually =
- isInStashedState && mControllers.taskbarStashController.supportsVisualStashing();
- float toAlignment =
- mLauncherState.isTaskbarAlignedWithHotseat(mLauncher) && !willStashVisually ? 1 : 0;
-
TaskbarStashController stashController = mControllers.taskbarStashController;
stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, isInStashedState);
Animator stashAnimator = stashController.applyStateWithoutStart(duration);
@@ -406,55 +389,23 @@
});
animatorSet.play(stashAnimator);
}
- if (mIconAlignmentForLauncherState.value == toAlignment) {
- // Already at expected value, but make sure we run the callback at the end.
- animatorSet.addListener(AnimatorListeners.forEndCallback(
- this::onIconAlignmentRatioChangedForStateTransition));
- }
- if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) {
- // If we're already animating to the value, just leave it be instead of restarting it.
- mIconAlignmentForLauncherState.finishAnimation();
- animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
- .setDuration(duration));
- if (DEBUG) {
- Log.d(TAG, "mIconAlignmentForLauncherState - "
- + mIconAlignmentForLauncherState.value
- + " -> " + toAlignment + ": " + duration);
- }
- animatorSet.setInterpolator(EMPHASIZED);
- }
}
- private boolean isResumed() {
- return (mState & FLAG_RESUMED) != 0;
+ private boolean isInLauncher() {
+ return (mState & FLAGS_LAUNCHER) != 0;
}
- private boolean isRecentsAnimationRunning() {
- return (mState & FLAG_RECENTS_ANIMATION_RUNNING) != 0;
- }
-
- private void onIconAlignmentRatioChangedForStateTransition() {
- if (!isResumed() && mTaskBarRecentsAnimationListener == null) {
- return;
- }
- onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioForLauncherState);
- }
-
- private void onIconAlignmentRatioChangedForAppAndHomeTransition() {
- onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioBetweenAppAndHome);
- }
-
- private void onIconAlignmentRatioChanged(Supplier<AnimatedFloat> alignmentSupplier) {
- if (mControllers == null) {
- return;
- }
- AnimatedFloat animatedFloat = alignmentSupplier.get();
+ private void onIconAlignmentRatioChanged() {
float currentValue = mIconAlphaForHome.getValue();
- boolean taskbarWillBeVisible = animatedFloat.value < 1;
+ boolean taskbarWillBeVisible = mIconAlignment.value < 1;
boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0)
|| (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0);
- updateIconAlignment(animatedFloat.value, animatedFloat.getEndValue());
+ mControllers.taskbarViewController.setLauncherIconAlignment(
+ mIconAlignment.value, mIconAlignment.getEndValue(), mLauncher.getDeviceProfile());
+ mControllers.navbarButtonsViewController.updateTaskbarAlignment(mIconAlignment.value);
+ // Switch taskbar and hotseat in last frame
+ mIconAlphaForHome.setValue(taskbarWillBeVisible ? 1 : 0);
// Sync the first frame where we swap taskbar and hotseat.
if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
@@ -464,28 +415,6 @@
}
}
- private void updateIconAlignment(float alignment, Float endAlignment) {
- mControllers.taskbarViewController.setLauncherIconAlignment(
- alignment, endAlignment, mLauncher.getDeviceProfile());
-
- // Switch taskbar and hotseat in last frame
- setTaskbarViewVisible(alignment < 1);
- mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment);
- }
-
- private AnimatedFloat getCurrentIconAlignmentRatioBetweenAppAndHome() {
- return mIconAlignmentForResumedState.value > mIconAlignmentForGestureState.value
- ? mIconAlignmentForResumedState : mIconAlignmentForGestureState;
- }
-
- private AnimatedFloat getCurrentIconAlignmentRatioForLauncherState() {
- return mIconAlignmentForLauncherState;
- }
-
- private void setTaskbarViewVisible(boolean isVisible) {
- mIconAlphaForHome.setValue(isVisible ? 1 : 0);
- }
-
private final class TaskBarRecentsAnimationListener implements
RecentsAnimationCallbacks.RecentsAnimationListener {
private final RecentsAnimationCallbacks mCallbacks;
@@ -515,11 +444,11 @@
updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, false);
updateStateForFlag(FLAG_RESUMED, launcherResumed);
applyState();
- // Set this last because applyState() might also animate it.
- mIconAlignmentForResumedState.cancelAnimation();
- mIconAlignmentForResumedState.updateValue(launcherResumed ? 1 : 0);
TaskbarStashController controller = mControllers.taskbarStashController;
+ if (DEBUG) {
+ Log.d(TAG, "endGestureStateOverride - FLAG_IN_APP: " + finishedToApp);
+ }
controller.updateStateForFlag(FLAG_IN_APP, finishedToApp);
controller.applyState();
}
@@ -527,29 +456,24 @@
private static String getStateString(int flags) {
StringJoiner str = new StringJoiner("|");
- str.add((flags & FLAG_RESUMED) != 0 ? "FLAG_RESUMED" : "");
- str.add((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0
- ? "FLAG_RECENTS_ANIMATION_RUNNING" : "");
- str.add((flags & FLAG_TRANSITION_STATE_RUNNING) != 0
- ? "FLAG_TRANSITION_STATE_RUNNING" : "");
+ if ((flags & FLAG_RESUMED) != 0) {
+ str.add("FLAG_RESUMED");
+ }
+ if ((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0) {
+ str.add("FLAG_RECENTS_ANIMATION_RUNNING");
+ }
+ if ((flags & FLAG_TRANSITION_STATE_RUNNING) != 0) {
+ str.add("FLAG_TRANSITION_STATE_RUNNING");
+ }
return str.toString();
}
protected void dumpLogs(String prefix, PrintWriter pw) {
pw.println(prefix + "TaskbarLauncherStateController:");
-
pw.println(String.format(
- "%s\tmIconAlignmentForResumedState=%.2f",
+ "%s\tmIconAlignment=%.2f",
prefix,
- mIconAlignmentForResumedState.value));
- pw.println(String.format(
- "%s\tmIconAlignmentForGestureState=%.2f",
- prefix,
- mIconAlignmentForGestureState.value));
- pw.println(String.format(
- "%s\tmIconAlignmentForLauncherState=%.2f",
- prefix,
- mIconAlignmentForLauncherState.value));
+ mIconAlignment.value));
pw.println(String.format(
"%s\tmTaskbarBackgroundAlpha=%.2f", prefix, mTaskbarBackgroundAlpha.value));
pw.println(String.format(
@@ -558,13 +482,9 @@
pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
pw.println(String.format("%s\tmLauncherState=%s", prefix, mLauncherState));
pw.println(String.format(
- "%s\tmIsAnimatingToLauncherViaGesture=%b",
+ "%s\tmIsAnimatingToLauncher=%b",
prefix,
- mIsAnimatingToLauncherViaGesture));
- pw.println(String.format(
- "%s\tmIsAnimatingToLauncherViaResume=%b",
- prefix,
- mIsAnimatingToLauncherViaResume));
+ mIsAnimatingToLauncher));
pw.println(String.format(
"%s\tmShouldDelayLauncherStateAnim=%b", prefix, mShouldDelayLauncherStateAnim));
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 00d5083..16dd90d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -102,6 +102,9 @@
private int mThemeIconsColor;
+ private final DeviceProfile.OnDeviceProfileChangeListener mDeviceProfileChangeListener =
+ dp -> commitRunningAppsToUI();
+
public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) {
mActivity = activity;
mTaskbarView = taskbarView;
@@ -129,10 +132,13 @@
controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY();
mTaskbarNavButtonTranslationYForInAppDisplay = controllers.navbarButtonsViewController
.getTaskbarNavButtonTranslationYForInAppDisplay();
+
+ mActivity.addOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
}
public void onDestroy() {
LauncherAppState.getInstance(mActivity).getModel().removeCallbacks(mModelCallbacks);
+ mActivity.removeOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
mModelCallbacks.unregisterListeners();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
index 81acda3..076900c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/VoiceInteractionWindowController.kt
@@ -77,7 +77,7 @@
fadeStashedHandle.end()
}
- moveTaskbarBackgroundToAppropriateLayer()
+ moveTaskbarBackgroundToAppropriateLayer(skipAnim)
}
/**
@@ -86,24 +86,28 @@
* OR
* Removes the temporary window and show the TaskbarDragLayer background again.
*/
- private fun moveTaskbarBackgroundToAppropriateLayer() {
+ private fun moveTaskbarBackgroundToAppropriateLayer(skipAnim: Boolean) {
val taskbarBackgroundOverride = controllers.taskbarDragLayerController
.overrideBackgroundAlpha
val moveToLowerLayer = isVoiceInteractionWindowVisible
- if (moveToLowerLayer) {
+ val onWindowsSynchronized = if (moveToLowerLayer) {
// First add the temporary window, then hide the overlapping taskbar background.
- context.addWindowView(separateWindowForTaskbarBackground, separateWindowLayoutParams)
- ViewRootSync.synchronizeNextDraw(separateWindowForTaskbarBackground, context.dragLayer
- ) {
- taskbarBackgroundOverride.updateValue(0f)
- }
+ context.addWindowView(separateWindowForTaskbarBackground, separateWindowLayoutParams);
+ { taskbarBackgroundOverride.updateValue(0f) }
} else {
// First reapply the original taskbar background, then remove the temporary window.
- taskbarBackgroundOverride.updateValue(1f)
- ViewRootSync.synchronizeNextDraw(separateWindowForTaskbarBackground, context.dragLayer
- ) {
- context.removeWindowView(separateWindowForTaskbarBackground)
- }
+ taskbarBackgroundOverride.updateValue(1f);
+ { context.removeWindowView(separateWindowForTaskbarBackground) }
+ }
+
+ if (skipAnim) {
+ onWindowsSynchronized()
+ } else {
+ ViewRootSync.synchronizeNextDraw(
+ separateWindowForTaskbarBackground,
+ context.dragLayer,
+ onWindowsSynchronized
+ )
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
index a1385c4..0372f67 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
@@ -41,6 +41,7 @@
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.taskbar.BaseTaskbarContext;
import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.taskbar.TaskbarDragController;
import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.testing.TestLogging;
@@ -72,7 +73,7 @@
TaskbarAllAppsContext(
TaskbarActivityContext taskbarContext,
TaskbarAllAppsController windowController,
- TaskbarStashController taskbarStashController) {
+ TaskbarControllers taskbarControllers) {
super(taskbarContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null));
mTaskbarContext = taskbarContext;
mWindowController = windowController;
@@ -86,9 +87,10 @@
this,
slideInView,
windowController,
- taskbarStashController);
+ taskbarControllers);
mAppsView = slideInView.getAppsView();
+ TaskbarStashController taskbarStashController = taskbarControllers.taskbarStashController;
mWillTaskbarBeVisuallyStashed = taskbarStashController.supportsVisualStashing();
mStashedTaskbarHeight = taskbarStashController.getStashedHeight();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index 6c43e50..1671a0f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -144,9 +144,7 @@
// to catch invalid states.
mControllers.getSharedState().allAppsVisible = true;
- mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext,
- this,
- mControllers.taskbarStashController);
+ mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext, this, mControllers);
mAllAppsContext.getDragController().init(mControllers);
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
Optional.ofNullable(mAllAppsContext.getSystemService(WindowManager.class))
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 0e62da3..9d48c8d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -30,13 +30,10 @@
import com.android.launcher3.R;
import com.android.launcher3.views.AbstractSlideInView;
-import java.util.Optional;
-
/** Wrapper for taskbar all apps with slide-in behavior. */
public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarAllAppsContext>
implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
private TaskbarAllAppsContainerView mAppsView;
- private OnCloseListener mOnCloseBeginListener;
private float mShiftRange;
public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs) {
@@ -72,14 +69,8 @@
return mAppsView;
}
- /** Callback invoked when the view is beginning to close (e.g. close animation is started). */
- void setOnCloseBeginListener(OnCloseListener onCloseBeginListener) {
- mOnCloseBeginListener = onCloseBeginListener;
- }
-
@Override
protected void handleClose(boolean animate) {
- Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
handleClose(animate,
ALL_APPS.getTransitionDuration(mActivityContext, false /* isToState */));
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
index a39e872..b0d3528 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -22,6 +22,8 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.appprediction.AppsDividerView;
import com.android.launcher3.appprediction.PredictionRowView;
+import com.android.launcher3.taskbar.NavbarButtonsViewController;
+import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.taskbar.TaskbarStashController;
/**
@@ -34,17 +36,19 @@
private final TaskbarAllAppsSlideInView mSlideInView;
private final TaskbarAllAppsContainerView mAppsView;
private final TaskbarStashController mTaskbarStashController;
+ private final NavbarButtonsViewController mNavbarButtonsViewController;
TaskbarAllAppsViewController(
TaskbarAllAppsContext context,
TaskbarAllAppsSlideInView slideInView,
TaskbarAllAppsController windowController,
- TaskbarStashController taskbarStashController) {
+ TaskbarControllers taskbarControllers) {
mContext = context;
mSlideInView = slideInView;
mAppsView = mSlideInView.getAppsView();
- mTaskbarStashController = taskbarStashController;
+ mTaskbarStashController = taskbarControllers.taskbarStashController;
+ mNavbarButtonsViewController = taskbarControllers.navbarButtonsViewController;
setUpIconLongClick();
setUpAppDivider();
@@ -83,7 +87,9 @@
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, true);
mTaskbarStashController.applyState(
ALL_APPS.getTransitionDuration(mContext, true /* isToState */));
+ mNavbarButtonsViewController.setSlideInViewVisible(true);
mSlideInView.setOnCloseBeginListener(() -> {
+ mNavbarButtonsViewController.setSlideInViewVisible(false);
AbstractFloatingView.closeOpenContainer(
mContext, AbstractFloatingView.TYPE_ACTION_POPUP);
// Post in case view is closing due to gesture navigation. If a gesture is in progress,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 192ac62..4ca27b1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -29,7 +29,6 @@
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_WIDGET_PICKER_DEPTH;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
@@ -559,10 +558,8 @@
@Override
protected void onScreenOff() {
super.onScreenOff();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- RecentsView recentsView = getOverviewPanel();
- recentsView.finishRecentsAnimation(true /* toRecents */, null);
- }
+ RecentsView recentsView = getOverviewPanel();
+ recentsView.finishRecentsAnimation(true /* toRecents */, null);
}
/**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 0723f8a..910b99b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -42,6 +42,8 @@
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.quickstep.util.AnimUtils;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -123,12 +125,19 @@
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
mLauncher.getDeviceProfile());
+ SplitAnimationTimings timings =
+ AnimUtils.getDeviceOverviewToSplitTimings(mLauncher.getDeviceProfile().isTablet);
+
mRecentsView.createSplitSelectInitAnimation(builder,
toState.getTransitionDuration(mLauncher, true /* isToState */));
- // Add properties to shift remaining taskViews to get out of placeholder view
+ // Shift tasks vertically downward to get out of placeholder view
builder.setFloat(mRecentsView, taskViewsFloat.first,
- toState.getSplitSelectTranslation(mLauncher), LINEAR);
- builder.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
+ toState.getSplitSelectTranslation(mLauncher),
+ timings.getGridSlidePrimaryInterpolator());
+ // Zero out horizontal translation
+ builder.setFloat(mRecentsView, taskViewsFloat.second,
+ 0,
+ timings.getGridSlideSecondaryInterpolator());
if (!animate) {
AnimatorSet as = builder.buildAnim();
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 6f07568..d075750 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -26,6 +26,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.Themes;
import com.android.quickstep.util.LayoutUtils;
@@ -104,7 +105,12 @@
@Override
public boolean isTaskbarStashed(Launcher launcher) {
- return true;
+ return !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
+ }
+
+ @Override
+ public boolean isTaskbarAlignedWithHotseat(Launcher launcher) {
+ return !FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get();
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 1e90aaf..5eeeb36 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -191,12 +191,16 @@
} else if (fromState == NORMAL && toState == ALL_APPS) {
AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
} else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) {
- SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
+ SplitAnimationTimings timings = mActivity.getDeviceProfile().isTablet
+ ? SplitAnimationTimings.TABLET_OVERVIEW_TO_SPLIT
+ : SplitAnimationTimings.PHONE_OVERVIEW_TO_SPLIT;
config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR,
timings.getActionsFadeStartOffset(),
timings.getActionsFadeEndOffset()));
- } else if (fromState == NORMAL && toState == OVERVIEW_SPLIT_SELECT) {
- SplitAnimationTimings timings = SplitAnimationTimings.NORMAL_TO_SPLIT;
+ } else if ((fromState == NORMAL || fromState == ALL_APPS)
+ && toState == OVERVIEW_SPLIT_SELECT) {
+ // Splitting from Home is currently only available on tablets
+ SplitAnimationTimings timings = SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
config.setInterpolator(ANIM_SCRIM_FADE, clampToProgress(LINEAR,
timings.getScrimFadeInStartOffset(),
timings.getScrimFadeInEndOffset()));
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
index 430053d..8babd34 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
@@ -44,8 +44,13 @@
@Override
public int getTransitionDuration(Context context, boolean isToState) {
- return isToState
- ? SplitAnimationTimings.ENTER_DURATION
- : SplitAnimationTimings.ABORT_DURATION;
+ boolean isTablet = ((Launcher) context).getDeviceProfile().isTablet;
+ if (isToState && isTablet) {
+ return SplitAnimationTimings.TABLET_ENTER_DURATION;
+ } else if (isToState && !isTablet) {
+ return SplitAnimationTimings.PHONE_ENTER_DURATION;
+ } else {
+ return SplitAnimationTimings.ABORT_DURATION;
+ }
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 30bb892..40dfd82 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -25,7 +25,6 @@
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_TRANSLATION;
import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -139,9 +138,7 @@
AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
builder);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- builder.addOnFrameCallback(recentsView::redrawLiveTile);
- }
+ builder.addOnFrameCallback(recentsView::redrawLiveTile);
AbstractFloatingView.closeOpenContainer(mLauncher, AbstractFloatingView.TYPE_TASK_MENU);
} else if (mStartState == ALL_APPS) {
@@ -182,11 +179,9 @@
boolean success = interpolatedProgress >= SUCCESS_TRANSITION_PROGRESS
|| (velocity < 0 && fling);
if (success) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- RecentsView recentsView = mLauncher.getOverviewPanel();
- recentsView.switchToScreenshot(null,
- () -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
- }
+ RecentsView recentsView = mLauncher.getOverviewPanel();
+ recentsView.switchToScreenshot(null,
+ () -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
if (mStartState.overviewUi) {
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState))
.animateWithVelocity(velocity);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index f3630c1..9106a8f 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -26,7 +26,6 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@@ -400,12 +399,6 @@
this::resetStateForAnimationCancel);
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED | STATE_FINISH_WITH_NO_END,
this::resetStateForAnimationCancel);
-
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mStateCallback.addChangeListener(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
- | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
- (b) -> mRecentsView.setRunningTaskHidden(!b));
- }
}
protected boolean onActivityInit(Boolean alreadyOnHome) {
@@ -583,14 +576,10 @@
}
private void onDeferredActivityLaunch() {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mActivityInterface.switchRunningTaskViewToScreenshot(
- null, () -> {
- mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
- });
- } else {
- mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
- }
+ mActivityInterface.switchRunningTaskViewToScreenshot(
+ null, () -> {
+ mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
+ });
}
private void setupRecentsViewUi() {
@@ -1010,8 +999,8 @@
switch (endTarget) {
case HOME:
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
- // Notify swipe-to-home (recents animation) is finished
- SystemUiProxy.INSTANCE.get(mContext).notifySwipeToHomeFinished();
+ // Notify the SysUI to use fade-in animation when entering PiP
+ SystemUiProxy.INSTANCE.get(mContext).setPipAnimationTypeToAlpha();
break;
case RECENTS:
mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -1719,8 +1708,7 @@
}
private void invalidateHandler() {
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get() || !mActivityInterface.isInLiveTileMode()
- || mGestureState.getEndTarget() != RECENTS) {
+ if (!mActivityInterface.isInLiveTileMode() || mGestureState.getEndTarget() != RECENTS) {
mInputConsumerProxy.destroy();
mTaskAnimationManager.setLiveTileCleanUpHandler(null);
}
@@ -1765,10 +1753,6 @@
* continued quick switch gesture, which cancels the previous handler but doesn't invalidate it.
*/
private void resetLauncherListeners() {
- // Reset the callback for deferred activity launches
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mActivityInterface.setOnDeferredActivityLaunchCallback(null);
- }
mActivity.getRootView().setOnApplyWindowInsetsListener(null);
mRecentsView.removeOnScrollChangedListener(mOnRecentsScrollListener);
@@ -1790,7 +1774,6 @@
mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
} else {
final int runningTaskId = mGestureState.getRunningTaskId();
- final boolean refreshView = !ENABLE_QUICKSTEP_LIVE_TILE.get() /* refreshView */;
boolean finishTransitionPosted = false;
if (mRecentsAnimationController != null) {
// Update the screenshot of the task
@@ -1801,14 +1784,14 @@
mRecentsAnimationController.screenshotTask(runningTaskId);
MAIN_EXECUTOR.execute(() -> {
mTaskSnapshot = taskSnapshot;
- if (!updateThumbnail(runningTaskId, refreshView)) {
+ if (!updateThumbnail(runningTaskId, false /* refreshView */)) {
setScreenshotCapturedState();
}
});
});
return;
}
- finishTransitionPosted = updateThumbnail(runningTaskId, refreshView);
+ finishTransitionPosted = updateThumbnail(runningTaskId, false /* refreshView */);
}
if (!finishTransitionPosted) {
setScreenshotCapturedState();
@@ -1846,17 +1829,9 @@
}
private void finishCurrentTransitionToRecents() {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
- if (mRecentsAnimationController != null) {
- mRecentsAnimationController.detachNavigationBarFromApp(true);
- }
- } else if (!hasTargets() || mRecentsAnimationController == null) {
- // If there are no targets or the animation not started, then there is nothing to finish
- mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
- } else {
- mRecentsAnimationController.finish(true /* toRecents */,
- () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
+ mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
+ if (mRecentsAnimationController != null) {
+ mRecentsAnimationController.detachNavigationBarFromApp(true);
}
ActiveGestureLog.INSTANCE.addLog(
/* event= */ "finishRecentsAnimation",
@@ -1920,13 +1895,11 @@
}
endLauncherTransitionController();
mRecentsView.onSwipeUpAnimationSuccess();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mTaskAnimationManager.setLiveTileCleanUpHandler(() -> {
- mRecentsView.cleanupRemoteTargets();
- mInputConsumerProxy.destroy();
- });
- mTaskAnimationManager.enableLiveTileRestartListener();
- }
+ mTaskAnimationManager.setLiveTileCleanUpHandler(() -> {
+ mRecentsView.cleanupRemoteTargets();
+ mInputConsumerProxy.destroy();
+ });
+ mTaskAnimationManager.enableLiveTileRestartListener();
SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView());
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java
index a166553..b06b894 100644
--- a/quickstep/src/com/android/quickstep/AnimatedFloat.java
+++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java
@@ -135,6 +135,13 @@
}
/**
+ * Returns whether we are currently not animating, and the animation's value matches the given.
+ */
+ public boolean isSettledOnValue(float endValue) {
+ return !isAnimating() && value == endValue;
+ }
+
+ /**
* Returns the value we are animating to, or {@code null} if we are not currently animating.
*/
public Float getEndValue() {
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index 466abbe..6e963f3 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
@@ -120,8 +119,7 @@
public RecentsView getVisibleRecentsView() {
RecentsActivity activity = getCreatedActivity();
if (activity != null) {
- if (activity.hasBeenResumed()
- || (ENABLE_QUICKSTEP_LIVE_TILE.get() && isInLiveTileMode())) {
+ if (activity.hasBeenResumed() || isInLiveTileMode()) {
return activity.getOverviewPanel();
}
}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 1127e2c..1cb17cb 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.animation.Animator;
@@ -203,8 +202,7 @@
private Launcher getVisibleLauncher() {
Launcher launcher = getCreatedActivity();
return (launcher != null) && launcher.isStarted()
- && ((ENABLE_QUICKSTEP_LIVE_TILE.get() && isInLiveTileMode())
- || launcher.hasBeenResumed()) ? launcher : null;
+ && (isInLiveTileMode() || launcher.hasBeenResumed()) ? launcher : null;
}
@Override
@@ -213,7 +211,7 @@
if (launcher == null) {
return false;
}
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isInLiveTileMode()) {
+ if (isInLiveTileMode()) {
RecentsView recentsView = getVisibleRecentsView();
if (recentsView == null) {
return false;
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 36ca993..d1533f0 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -84,7 +84,8 @@
final View workspaceView = findWorkspaceView(launchCookies,
mRecentsView.getRunningTaskView());
- boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow();
+ boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow()
+ && workspaceView.getHeight() > 0;
mActivity.getRootView().setForceHideBackArrow(true);
if (!TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index dea4e48..6b616b1 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -255,7 +255,8 @@
TaskLoadResult allTasks = new TaskLoadResult(requestId, loadKeysOnly, rawTasks.size());
for (GroupedRecentTaskInfo rawTask : rawTasks) {
if (rawTask.getType() == GroupedRecentTaskInfo.TYPE_FREEFORM) {
- // TODO: add entry for freeform tasks
+ GroupTask desktopTask = createDesktopTask(rawTask);
+ allTasks.add(desktopTask);
continue;
}
ActivityManager.RecentTaskInfo taskInfo1 = rawTask.getTaskInfo1();
@@ -283,6 +284,16 @@
return allTasks;
}
+ private GroupTask createDesktopTask(GroupedRecentTaskInfo taskInfo) {
+ // TODO(b/244348395): create a subclass of GroupTask for desktop tile
+ // We need a single task information as the primary task. Use the first task
+ Task.TaskKey key = new Task.TaskKey(taskInfo.getTaskInfo1());
+ Task task = new Task(key);
+ task.desktopTile = true;
+ task.topActivity = key.sourceComponent;
+ return new GroupTask(task, null, null);
+ }
+
private SplitConfigurationOptions.SplitBounds convertSplitBounds(
SplitBounds shellSplitBounds) {
return shellSplitBounds == null ?
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index c879494..4f5e216 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
@@ -393,13 +392,9 @@
}
public void startHome() {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- RecentsView recentsView = getOverviewPanel();
- recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
- this::startHomeInternal));
- } else {
- startHomeInternal();
- }
+ RecentsView recentsView = getOverviewPanel();
+ recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
+ this::startHomeInternal));
}
private void startHomeInternal() {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index dcf685a..35d7394 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -58,6 +58,7 @@
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.system.smartspace.SmartspaceState;
import com.android.wm.shell.back.IBackAnimation;
+import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.floating.IFloatingTasks;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
@@ -95,6 +96,7 @@
private IStartingWindow mStartingWindow;
private IRecentTasks mRecentTasks;
private IBackAnimation mBackAnimation;
+ private IDesktopMode mDesktopMode;
private final DeathRecipient mSystemUiProxyDeathRecipient = () -> {
MAIN_EXECUTOR.execute(() -> clearProxy());
};
@@ -169,7 +171,7 @@
IFloatingTasks floatingTasks, IOneHanded oneHanded, IShellTransitions shellTransitions,
IStartingWindow startingWindow, IRecentTasks recentTasks,
ISysuiUnlockAnimationController sysuiUnlockAnimationController,
- IBackAnimation backAnimation) {
+ IBackAnimation backAnimation, IDesktopMode desktopMode) {
unlinkToDeath();
mSystemUiProxy = proxy;
mPip = pip;
@@ -181,10 +183,11 @@
mSysuiUnlockAnimationController = sysuiUnlockAnimationController;
mRecentTasks = recentTasks;
mBackAnimation = backAnimation;
+ mDesktopMode = desktopMode;
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
if (mPipAnimationListener != null && mPip != null) {
- setPinnedStackAnimationListener(mPipAnimationListener);
+ setPipAnimationListener(mPipAnimationListener);
}
if (mSplitScreenListener != null && mSplitScreen != null) {
registerSplitScreenListener(mSplitScreenListener);
@@ -207,7 +210,7 @@
}
public void clearProxy() {
- setProxy(null, null, null, null, null, null, null, null, null, null);
+ setProxy(null, null, null, null, null, null, null, null, null, null, null);
}
// TODO(141886704): Find a way to remove this
@@ -354,20 +357,6 @@
}
}
- /**
- * Notifies that swipe-to-home action is finished.
- */
- @Override
- public void notifySwipeToHomeFinished() {
- if (mSystemUiProxy != null) {
- try {
- mSystemUiProxy.notifySwipeToHomeFinished();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed call notifySwipeToHomeFinished", e);
- }
- }
- }
-
@Override
public void notifyPrioritizedRotation(int rotation) {
if (mSystemUiProxy != null) {
@@ -472,12 +461,12 @@
}
/**
- * Sets listener to get pinned stack animation callbacks.
+ * Sets listener to get pip animation callbacks.
*/
- public void setPinnedStackAnimationListener(IPipAnimationListener listener) {
+ public void setPipAnimationListener(IPipAnimationListener listener) {
if (mPip != null) {
try {
- mPip.setPinnedStackAnimationListener(listener);
+ mPip.setPipAnimationListener(listener);
} catch (RemoteException e) {
Log.w(TAG, "Failed call setPinnedStackAnimationListener", e);
}
@@ -519,6 +508,19 @@
}
}
+ /**
+ * Sets the next pip animation type to be the alpha animation.
+ */
+ public void setPipAnimationTypeToAlpha() {
+ if (mPip != null) {
+ try {
+ mPip.setPipAnimationTypeToAlpha();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call setPipAnimationTypeToAlpha", e);
+ }
+ }
+ }
+
//
// Splitscreen
//
@@ -908,4 +910,19 @@
return false;
}
+
+ //
+ // Desktop Mode
+ //
+
+ /** Call shell to show all apps active on the desktop */
+ public void showDesktopApps() {
+ if (mDesktopMode != null) {
+ try {
+ mDesktopMode.showDesktopApps();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call showDesktopApps", e);
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index b9a1b06..7f16565 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
@@ -72,7 +71,7 @@
return;
}
BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+ if (activityInterface.isInLiveTileMode()
&& activityInterface.getCreatedActivity() != null) {
RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
if (recentsView != null) {
@@ -171,7 +170,7 @@
.map(RemoteAnimationTargetCompat::unwrap)
.toArray(RemoteAnimationTarget[]::new));
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+ if (activityInterface.isInLiveTileMode()
&& activityInterface.getCreatedActivity() != null) {
RecentsView recentsView =
activityInterface.getCreatedActivity().getOverviewPanel();
@@ -204,7 +203,7 @@
@Override
public boolean onSwitchToScreenshot(Runnable onFinished) {
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get() || !activityInterface.isInLiveTileMode()
+ if (!activityInterface.isInLiveTileMode()
|| activityInterface.getCreatedActivity() == null) {
// No need to switch since tile is already a screenshot.
onFinished.run();
@@ -266,7 +265,7 @@
return;
}
BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+ if (activityInterface.isInLiveTileMode()
&& activityInterface.getCreatedActivity() != null) {
RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
if (recentsView != null) {
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index e10cab6..d40f2ae 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -18,7 +18,6 @@
import static android.view.Surface.ROTATION_0;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
@@ -174,14 +173,10 @@
* @param callback callback to run, after switching to screenshot
*/
public void endLiveTileMode(@NonNull Runnable callback) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
- recentsView.switchToScreenshot(
- () -> recentsView.finishRecentsAnimation(true /* toRecents */,
- false /* shouldPip */, callback));
- } else {
- callback.run();
- }
+ RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
+ recentsView.switchToScreenshot(
+ () -> recentsView.finishRecentsAnimation(true /* toRecents */,
+ false /* shouldPip */, callback));
}
/**
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index a96524e..e7173f5 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -35,7 +35,6 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -637,7 +636,7 @@
};
}
pa.add(launcherAnim);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && recentsView.getRunningTaskIndex() != -1) {
+ if (recentsView.getRunningTaskIndex() != -1) {
pa.addOnFrameCallback(recentsView::redrawLiveTile);
}
anim.play(pa.buildAnim());
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index e207a1b..4476dcb 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -20,7 +20,6 @@
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.config.FeatureFlags.ASSISTANT_GIVES_LAUNCHER_FOCUS;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.MOTION_DOWN;
@@ -28,6 +27,7 @@
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_RECENT_TASKS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_BACK_ANIMATION;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_DESKTOP_MODE;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_FLOATING_TASKS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
@@ -111,6 +111,7 @@
import com.android.systemui.shared.system.smartspace.ISysuiUnlockAnimationController;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.wm.shell.back.IBackAnimation;
+import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.floating.IFloatingTasks;
import com.android.wm.shell.onehanded.IOneHanded;
import com.android.wm.shell.pip.IPip;
@@ -184,10 +185,12 @@
bundle.getBinder(KEY_EXTRA_RECENT_TASKS));
IBackAnimation backAnimation = IBackAnimation.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_SHELL_BACK_ANIMATION));
+ IDesktopMode desktopMode = IDesktopMode.Stub.asInterface(
+ bundle.getBinder(KEY_EXTRA_SHELL_DESKTOP_MODE));
MAIN_EXECUTOR.execute(() -> {
SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
splitscreen, floatingTasks, onehanded, shellTransitions, startingWindow,
- recentTasks, launcherUnlockAnimationController, backAnimation);
+ recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode);
TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()");
preloadOverview(true /* fromInit */);
});
@@ -951,8 +954,7 @@
boolean launcherResumedThroughShellTransition =
gestureState.getActivityInterface().isResumed()
&& !previousGestureState.isRecentsAnimationRunning();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()
- && gestureState.getActivityInterface().isInLiveTileMode()) {
+ if (gestureState.getActivityInterface().isInLiveTileMode()) {
return createOverviewInputConsumer(
previousGestureState,
gestureState,
@@ -1040,8 +1042,7 @@
previousGestureState.isRunningAnimationToLauncher();
boolean forcingOverviewInputConsumer =
ASSISTANT_GIVES_LAUNCHER_FOCUS.get() && forceOverviewInputConsumer;
- boolean isInLiveTileMode = ENABLE_QUICKSTEP_LIVE_TILE.get()
- && gestureState.getActivityInterface().isInLiveTileMode();
+ boolean isInLiveTileMode = gestureState.getActivityInterface().isInLiveTileMode();
reasonString.append(SUBSTRING_PREFIX)
.append(hasWindowFocus
? "activity has window focus"
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
index eca61bb..db4927a 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep.fallback;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.quickstep.RecentsActivity;
@@ -28,8 +26,7 @@
@Override
protected boolean isRecentsInteractive() {
- return mActivity.hasWindowFocus() || (ENABLE_QUICKSTEP_LIVE_TILE.get()
- && mActivity.getStateManager().getState().hasLiveTile());
+ return mActivity.hasWindowFocus() || mActivity.getStateManager().getState().hasLiveTile();
}
@Override
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index 6f35928..64165b6 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep.inputconsumers;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.media.AudioManager;
@@ -100,27 +99,23 @@
@Override
public void onHoverEvent(MotionEvent ev) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mActivity.dispatchGenericMotionEvent(ev);
- }
+ mActivity.dispatchGenericMotionEvent(ev);
}
@Override
public void onKeyEvent(KeyEvent ev) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- switch (ev.getKeyCode()) {
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_MUTE:
- MediaSessionManager mgr = mActivity.getSystemService(MediaSessionManager.class);
- mgr.dispatchVolumeKeyEventAsSystemService(ev,
- AudioManager.USE_DEFAULT_STREAM_TYPE);
- break;
- default:
- break;
- }
- mActivity.dispatchKeyEvent(ev);
+ switch (ev.getKeyCode()) {
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ MediaSessionManager mgr = mActivity.getSystemService(MediaSessionManager.class);
+ mgr.dispatchVolumeKeyEventAsSystemService(ev,
+ AudioManager.USE_DEFAULT_STREAM_TYPE);
+ break;
+ default:
+ break;
}
+ mActivity.dispatchKeyEvent(ev);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/AnimUtils.java b/quickstep/src/com/android/quickstep/util/AnimUtils.java
new file mode 100644
index 0000000..b7b7825
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/AnimUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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;
+
+/**
+ * Utility class containing methods to help manage animations, interpolators, and timings.
+ */
+public class AnimUtils {
+ /**
+ * Fetches device-specific timings for the Overview > Split animation
+ * (splitscreen initiated from Overview).
+ */
+ public static SplitAnimationTimings getDeviceOverviewToSplitTimings(boolean isTablet) {
+ return isTablet
+ ? SplitAnimationTimings.TABLET_OVERVIEW_TO_SPLIT
+ : SplitAnimationTimings.PHONE_OVERVIEW_TO_SPLIT;
+ }
+
+ /**
+ * Fetches device-specific timings for the Split > Confirm animation
+ * (splitscreen confirmed by selecting a second app).
+ */
+ public static SplitAnimationTimings getDeviceSplitToConfirmTimings(boolean isTablet) {
+ return isTablet
+ ? SplitAnimationTimings.TABLET_SPLIT_TO_CONFIRM
+ : SplitAnimationTimings.PHONE_SPLIT_TO_CONFIRM;
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
index f44796b..e189a66 100644
--- a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
@@ -16,39 +16,45 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
import android.view.animation.Interpolator;
/**
* Timings for the Overview > OverviewSplitSelect animation.
*/
-public class OverviewToSplitTimings implements SplitAnimationTimings {
- public int getPlaceholderFadeInStart() { return 0; }
- public int getPlaceholderFadeInEnd() { return 133; }
- public int getPlaceholderIconFadeInStart() { return 167; }
- public int getPlaceholderIconFadeInEnd() { return 250; }
- public int getStagedRectSlideStart() { return 0; }
- public int getStagedRectSlideEnd() { return 417; }
- public int getGridSlideStart() { return 67; }
- public int getGridSlideStagger() { return 16; }
- public int getGridSlideDuration() { return 500; }
- public int getActionsFadeStart() { return 0; }
- public int getActionsFadeEnd() { return 83; }
+abstract class OverviewToSplitTimings implements SplitAnimationTimings {
+ // Overwritten by device-specific timings
+ abstract public int getPlaceholderFadeInStart();
+ abstract public int getPlaceholderFadeInEnd();
+ abstract public int getPlaceholderIconFadeInStart();
+ abstract public int getPlaceholderIconFadeInEnd();
+ abstract public int getStagedRectSlideStart();
+ abstract public int getStagedRectSlideEnd();
+ abstract public int getGridSlideStart();
+ abstract public int getGridSlideStagger();
+ abstract public int getGridSlideDuration();
+
+ // Common timings
public int getIconFadeStart() { return 0; }
public int getIconFadeEnd() { return 83; }
+ public int getActionsFadeStart() { return 0; }
+ public int getActionsFadeEnd() { return 83; }
public int getInstructionsContainerFadeInStart() { return 167; }
public int getInstructionsContainerFadeInEnd() { return 250; }
public int getInstructionsTextFadeInStart() { return 217; }
public int getInstructionsTextFadeInEnd() { return 300; }
public int getInstructionsUnfoldStart() { return 167; }
public int getInstructionsUnfoldEnd() { return 500; }
+ public Interpolator getGridSlidePrimaryInterpolator() { return EMPHASIZED; }
+ public Interpolator getGridSlideSecondaryInterpolator() { return INSTANT; }
- public int getDuration() { return ENTER_DURATION; }
- public Interpolator getStagedRectXInterpolator() { return DEACCEL_2; }
- public Interpolator getStagedRectYInterpolator() { return DEACCEL_2; }
- public Interpolator getStagedRectScaleXInterpolator() { return DEACCEL_2; }
- public Interpolator getStagedRectScaleYInterpolator() { return DEACCEL_2; }
+ abstract public int getDuration();
+ abstract public Interpolator getStagedRectXInterpolator();
+ abstract public Interpolator getStagedRectYInterpolator();
+ abstract public Interpolator getStagedRectScaleXInterpolator();
+ abstract public Interpolator getStagedRectScaleYInterpolator();
public float getGridSlideStartOffset() {
return (float) getGridSlideStart() / getDuration();
diff --git a/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
new file mode 100644
index 0000000..f1dde53
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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 static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the Overview > OverviewSplitSelect animation on phones.
+ */
+public class PhoneOverviewToSplitTimings
+ extends OverviewToSplitTimings implements SplitAnimationTimings {
+ public int getPlaceholderFadeInStart() { return 0; }
+ public int getPlaceholderFadeInEnd() { return 133; }
+ public int getPlaceholderIconFadeInStart() { return 83; }
+ public int getPlaceholderIconFadeInEnd() { return 167; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 333; }
+ public int getGridSlideStart() { return 100; }
+ public int getGridSlideStagger() { return 0; }
+ public int getGridSlideDuration() { return 417; }
+
+ public int getDuration() { return PHONE_ENTER_DURATION; }
+ public Interpolator getStagedRectXInterpolator() { return EMPHASIZED; }
+ public Interpolator getStagedRectYInterpolator() { return EMPHASIZED; }
+ public Interpolator getStagedRectScaleXInterpolator() { return EMPHASIZED; }
+ public Interpolator getStagedRectScaleYInterpolator() { return EMPHASIZED; }
+}
diff --git a/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java
new file mode 100644
index 0000000..9e7351a
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/PhoneSplitToConfirmTimings.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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 static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the OverviewSplitSelect > confirmed animation on phones.
+ */
+public class PhoneSplitToConfirmTimings
+ extends SplitToConfirmTimings implements SplitAnimationTimings {
+ public int getPlaceholderFadeInStart() { return 0; }
+ public int getPlaceholderFadeInEnd() { return 133; }
+ public int getPlaceholderIconFadeInStart() { return 50; }
+ public int getPlaceholderIconFadeInEnd() { return 133; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 333; }
+
+ public int getDuration() { return PHONE_CONFIRM_DURATION; }
+ public Interpolator getStagedRectXInterpolator() { return EMPHASIZED; }
+ public Interpolator getStagedRectYInterpolator() { return EMPHASIZED; }
+ public Interpolator getStagedRectScaleXInterpolator() { return EMPHASIZED; }
+ public Interpolator getStagedRectScaleYInterpolator() { return EMPHASIZED; }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
index 133be03..2966fbb 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -16,19 +16,28 @@
package com.android.quickstep.util;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
import android.view.animation.Interpolator;
/**
* An interface that supports the centralization of timing information for splitscreen animations.
*/
public interface SplitAnimationTimings {
- int ENTER_DURATION = 866;
- int ABORT_DURATION = 500;
- int CONFIRM_DURATION = 383;
+ int TABLET_ENTER_DURATION = 866;
+ int TABLET_CONFIRM_DURATION = 383;
- SplitAnimationTimings OVERVIEW_TO_SPLIT = new OverviewToSplitTimings();
- SplitAnimationTimings NORMAL_TO_SPLIT = new NormalToSplitTimings();
- SplitAnimationTimings SPLIT_TO_CONFIRM = new SplitToConfirmTimings();
+ int PHONE_ENTER_DURATION = 517;
+ int PHONE_CONFIRM_DURATION = 333;
+
+ int ABORT_DURATION = 500;
+
+ SplitAnimationTimings TABLET_OVERVIEW_TO_SPLIT = new TabletOverviewToSplitTimings();
+ SplitAnimationTimings TABLET_HOME_TO_SPLIT = new TabletHomeToSplitTimings();
+ SplitAnimationTimings TABLET_SPLIT_TO_CONFIRM = new TabletSplitToConfirmTimings();
+
+ SplitAnimationTimings PHONE_OVERVIEW_TO_SPLIT = new PhoneOverviewToSplitTimings();
+ SplitAnimationTimings PHONE_SPLIT_TO_CONFIRM = new PhoneSplitToConfirmTimings();
// Shared methods
int getDuration();
@@ -75,8 +84,10 @@
default float getInstructionsTextFadeInEndOffset() { return 0; }
default float getInstructionsUnfoldStartOffset() { return 0; }
default float getInstructionsUnfoldEndOffset() { return 0; }
+ default Interpolator getGridSlidePrimaryInterpolator() { return LINEAR; }
+ default Interpolator getGridSlideSecondaryInterpolator() { return LINEAR; }
- // Defaults for NormalToSplit
+ // Defaults for HomeToSplit
default float getScrimFadeInStartOffset() { return 0; }
default float getScrimFadeInEndOffset() { return 0; }
diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
index 84cfb0b..3026e98 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
@@ -16,28 +16,29 @@
package com.android.quickstep.util;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-
import android.view.animation.Interpolator;
/**
* Timings for the OverviewSplitSelect > confirmed animation.
*/
-public class SplitToConfirmTimings implements SplitAnimationTimings {
- public int getPlaceholderFadeInStart() { return 0; }
- public int getPlaceholderFadeInEnd() { return 133; }
- public int getPlaceholderIconFadeInStart() { return 167; }
- public int getPlaceholderIconFadeInEnd() { return 250; }
- public int getStagedRectSlideStart() { return 0; }
- public int getStagedRectSlideEnd() { return 383; }
+abstract class SplitToConfirmTimings implements SplitAnimationTimings {
+ // Overwritten by device-specific timings
+ abstract public int getPlaceholderFadeInStart();
+ abstract public int getPlaceholderFadeInEnd();
+ abstract public int getPlaceholderIconFadeInStart();
+ abstract public int getPlaceholderIconFadeInEnd();
+ abstract public int getStagedRectSlideStart();
+ abstract public int getStagedRectSlideEnd();
+
+ // Common timings
public int getInstructionsFadeStart() { return 0; }
public int getInstructionsFadeEnd() { return 67; }
- public int getDuration() { return CONFIRM_DURATION; }
- public Interpolator getStagedRectXInterpolator() { return LINEAR; }
- public Interpolator getStagedRectYInterpolator() { return LINEAR; }
- public Interpolator getStagedRectScaleXInterpolator() { return LINEAR; }
- public Interpolator getStagedRectScaleYInterpolator() { return LINEAR; }
+ abstract public int getDuration();
+ abstract public Interpolator getStagedRectXInterpolator();
+ abstract public Interpolator getStagedRectYInterpolator();
+ abstract public Interpolator getStagedRectScaleXInterpolator();
+ abstract public Interpolator getStagedRectScaleYInterpolator();
public float getInstructionsFadeStartOffset() {
return (float) getInstructionsFadeStart() / getDuration();
diff --git a/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
similarity index 88%
rename from quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java
rename to quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
index 1bf5a5d..bf8612a 100644
--- a/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
@@ -21,9 +21,10 @@
import android.view.animation.Interpolator;
/**
- * Timings for the Normal > OverviewSplitSelect animation.
+ * Timings for the Home > OverviewSplitSelect animation on tablets.
*/
-public class NormalToSplitTimings extends OverviewToSplitTimings implements SplitAnimationTimings {
+public class TabletHomeToSplitTimings
+ extends TabletOverviewToSplitTimings implements SplitAnimationTimings {
@Override
public Interpolator getStagedRectXInterpolator() { return LINEAR; }
@Override
diff --git a/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
new file mode 100644
index 0000000..cbf46bf
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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 static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the Overview > OverviewSplitSelect animation on tablets.
+ */
+public class TabletOverviewToSplitTimings
+ extends OverviewToSplitTimings implements SplitAnimationTimings {
+ public int getPlaceholderFadeInStart() { return 0; }
+ public int getPlaceholderFadeInEnd() { return 133; }
+ public int getPlaceholderIconFadeInStart() { return 167; }
+ public int getPlaceholderIconFadeInEnd() { return 250; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 417; }
+ public int getGridSlideStart() { return 67; }
+ public int getGridSlideStagger() { return 16; }
+ public int getGridSlideDuration() { return 500; }
+
+ public int getDuration() { return TABLET_ENTER_DURATION; }
+ public Interpolator getStagedRectXInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectYInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectScaleXInterpolator() { return DEACCEL_2; }
+ public Interpolator getStagedRectScaleYInterpolator() { return DEACCEL_2; }
+}
diff --git a/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java
similarity index 60%
copy from quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java
copy to quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java
index 1bf5a5d..3ea8466 100644
--- a/quickstep/src/com/android/quickstep/util/NormalToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletSplitToConfirmTimings.java
@@ -21,23 +21,20 @@
import android.view.animation.Interpolator;
/**
- * Timings for the Normal > OverviewSplitSelect animation.
+ * Timings for the OverviewSplitSelect > confirmed animation on tablets.
*/
-public class NormalToSplitTimings extends OverviewToSplitTimings implements SplitAnimationTimings {
- @Override
+public class TabletSplitToConfirmTimings
+ extends SplitToConfirmTimings implements SplitAnimationTimings {
+ public int getPlaceholderFadeInStart() { return 0; }
+ public int getPlaceholderFadeInEnd() { return 133; }
+ public int getPlaceholderIconFadeInStart() { return 167; }
+ public int getPlaceholderIconFadeInEnd() { return 250; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 383; }
+
+ public int getDuration() { return TABLET_CONFIRM_DURATION; }
public Interpolator getStagedRectXInterpolator() { return LINEAR; }
- @Override
+ public Interpolator getStagedRectYInterpolator() { return LINEAR; }
public Interpolator getStagedRectScaleXInterpolator() { return LINEAR; }
- @Override
public Interpolator getStagedRectScaleYInterpolator() { return LINEAR; }
-
- public int getScrimFadeInStart() { return 0; }
- public int getScrimFadeInEnd() { return 167; }
-
- public float getScrimFadeInStartOffset() {
- return (float) getScrimFadeInStart() / getDuration();
- }
- public float getScrimFadeInEndOffset() {
- return (float) getScrimFadeInEnd() / getDuration();
- }
}
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 1a026fc..c03aa3f 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -17,7 +17,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.deltaRotation;
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -47,9 +46,9 @@
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.BaseActivityInterface;
import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
import com.android.quickstep.views.TaskView.FullscreenDrawParams;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
@@ -318,9 +317,9 @@
// mIsRecentsRtl is the inverse of TaskView RTL.
boolean isRtlEnabled = !mIsRecentsRtl;
mPositionHelper.updateThumbnailMatrix(
- mThumbnailPosition, mThumbnailData,
- mTaskRect.width(), mTaskRect.height(),
- mDp, mOrientationState.getRecentsActivityRotation(), isRtlEnabled);
+ mThumbnailPosition, mThumbnailData, mTaskRect.width(), mTaskRect.height(),
+ mDp.widthPx, mDp.taskbarSize, mDp.isTablet,
+ mOrientationState.getRecentsActivityRotation(), isRtlEnabled);
mPositionHelper.getMatrix().invert(mInversePositionMatrix);
if (DEBUG) {
Log.d(TAG, " taskRect: " + mTaskRect);
@@ -393,7 +392,7 @@
.withCornerRadius(getCurrentCornerRadius());
// If mDrawsBelowRecents is unset, no reordering will be enforced.
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mDrawsBelowRecents != null) {
+ if (mDrawsBelowRecents != null) {
// In legacy transitions, the animation leashes remain in same hierarchy in the
// TaskDisplayArea, so we don't want to bump the layer too high otherwise it will
// conflict with layers that WM core positions (ie. the input consumers). For shell
diff --git a/quickstep/src/com/android/quickstep/util/ViewCapture.java b/quickstep/src/com/android/quickstep/util/ViewCapture.java
index cfcfce0..6171c5d 100644
--- a/quickstep/src/com/android/quickstep/util/ViewCapture.java
+++ b/quickstep/src/com/android/quickstep/util/ViewCapture.java
@@ -421,7 +421,6 @@
out.visibility = this.visibility;
out.willNotDraw = this.willNotDraw;
out.clipChildren = this.clipChildren;
- out.next = this.next;
out.elevation = this.elevation;
}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 1a02f03..dc1ae52 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -30,6 +30,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.util.AnimUtils;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.TaskCornerRadius;
@@ -215,9 +216,19 @@
*/
public void addStagingAnimation(PendingAnimation animation, RectF startingBounds,
Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
- SplitAnimationTimings timings = fadeWithThumbnail
- ? SplitAnimationTimings.OVERVIEW_TO_SPLIT
- : SplitAnimationTimings.NORMAL_TO_SPLIT;
+ boolean isTablet = mActivity.getDeviceProfile().isTablet;
+ boolean splittingFromOverview = fadeWithThumbnail;
+ SplitAnimationTimings timings;
+
+ if (isTablet && splittingFromOverview) {
+ timings = SplitAnimationTimings.TABLET_OVERVIEW_TO_SPLIT;
+ } else if (!isTablet && splittingFromOverview) {
+ timings = SplitAnimationTimings.PHONE_OVERVIEW_TO_SPLIT;
+ } else {
+ // Splitting from Home is currently only available on tablets
+ timings = SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
+ }
+
addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
timings);
}
@@ -228,8 +239,11 @@
*/
public void addConfirmAnimation(PendingAnimation animation, RectF startingBounds,
Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
+ SplitAnimationTimings timings =
+ AnimUtils.getDeviceSplitToConfirmTimings(mActivity.getDeviceProfile().isTablet);
+
addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
- SplitAnimationTimings.SPLIT_TO_CONFIRM);
+ timings);
}
/**
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 08a17c4..abace7c 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -82,10 +82,11 @@
private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3;
private static final int INDEX_SHARE_TARGET_ALPHA = 4;
- public @interface SplitButtonDisabledFlags { }
-
+ public @interface SplitButtonHiddenFlags { }
public static final int FLAG_IS_NOT_TABLET = 1 << 0;
- public static final int FLAG_SINGLE_TASK = 1 << 1;
+
+ public @interface SplitButtonDisabledFlags { }
+ public static final int FLAG_SINGLE_TASK = 1 << 0;
private MultiValueAlpha mMultiValueAlpha;
private Button mSplitButton;
@@ -96,6 +97,9 @@
@ActionsDisabledFlags
protected int mDisabledFlags;
+ @SplitButtonHiddenFlags
+ private int mSplitButtonHiddenFlags;
+
@SplitButtonDisabledFlags
private int mSplitButtonDisabledFlags;
@@ -191,20 +195,40 @@
}
boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
LayoutUtils.setViewEnabled(this, isEnabled);
+ updateSplitButtonEnabledState();
}
/**
- * Updates the proper flags to indicate whether the "Split screen" button should be enabled.
+ * Updates the proper flags to indicate whether the "Split screen" button should be hidden.
*
- * @param flag The flag to update.
- * @param enable Whether to enable the disable flag: True will cause view to be disabled.
+ * @param flag The flag to update.
+ * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
*/
- public void updateSplitButtonFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
+ public void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag, boolean enable) {
+ if (enable) {
+ mSplitButtonHiddenFlags |= flag;
+ } else {
+ mSplitButtonHiddenFlags &= ~flag;
+ }
+ if (mSplitButton == null) return;
+ boolean shouldBeVisible = mSplitButtonHiddenFlags == 0;
+ mSplitButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
+ findViewById(R.id.action_split_space).setVisibility(shouldBeVisible ? VISIBLE : GONE);
+ }
+
+ /**
+ * Updates the proper flags to indicate whether the "Split screen" button should be disabled.
+ *
+ * @param flag The flag to update.
+ * @param enable Whether to enable the disable flag: True will cause view to be disabled.
+ */
+ public void updateSplitButtonDisabledFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
if (enable) {
mSplitButtonDisabledFlags |= flag;
} else {
mSplitButtonDisabledFlags &= ~flag;
}
+ updateSplitButtonEnabledState();
}
public AlphaProperty getContentAlpha() {
@@ -289,16 +313,16 @@
}
/**
- * Shows/hides the "Split" button based on the status of mHiddenFlags.
+ * Enables/disables the "Split" button based on the status of mSplitButtonDisabledFlags and
+ * mDisabledFlags.
*/
- public void updateSplitButtonVisibility() {
+ private void updateSplitButtonEnabledState() {
if (mSplitButton == null) {
return;
}
- boolean shouldBeVisible = mSplitButtonDisabledFlags == 0
- // and neither of these flags are active
- && (mHiddenFlags & (HIDDEN_SPLIT_SCREEN | HIDDEN_SPLIT_SELECT_ACTIVE)) == 0;
- mSplitButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
- findViewById(R.id.action_split_space).setVisibility(shouldBeVisible ? VISIBLE : GONE);
+ boolean isParentEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
+ boolean shouldBeEnabled = mSplitButtonDisabledFlags == 0 && isParentEnabled;
+ mSplitButton.setEnabled(shouldBeEnabled);
}
+
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 96607a0..68b80c2 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -41,7 +41,6 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
@@ -171,6 +170,7 @@
import com.android.quickstep.ViewUtils;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.AnimUtils;
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
@@ -816,8 +816,7 @@
}
super.dispatchDraw(canvas);
}
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
- && mRemoteTargetHandles != null) {
+ if (mEnableDrawingLiveTile && mRemoteTargetHandles != null) {
redrawLiveTile();
}
}
@@ -940,7 +939,7 @@
.setSyncTransactionApplier(mSyncTransactionApplier));
RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this);
mIPipAnimationListener.setActivityAndRecentsView(mActivity, this);
- SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(
+ SystemUiProxy.INSTANCE.get(getContext()).setPipAnimationListener(
mIPipAnimationListener);
mOrientationState.initListeners();
SplitScreenBounds.INSTANCE.addOnChangeListener(this);
@@ -959,7 +958,7 @@
.setSyncTransactionApplier(null));
executeSideTaskLaunchCallback();
RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this);
- SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null);
+ SystemUiProxy.INSTANCE.get(getContext()).setPipAnimationListener(null);
SplitScreenBounds.INSTANCE.removeOnChangeListener(this);
mIPipAnimationListener.setActivityAndRecentsView(null, null);
mOrientationState.destroyListeners();
@@ -1628,22 +1627,20 @@
taskView.setTaskThumbnailSplashAlpha(mTaskThumbnailSplashAlpha);
}
}
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- // resetTaskVisuals is called at the end of dismiss animation which could update
- // primary and secondary translation of the live tile cut out. We will need to do so
- // here accordingly.
- runActionOnRemoteHandles(remoteTargetHandle -> {
- TaskViewSimulator simulator = remoteTargetHandle.getTaskViewSimulator();
- simulator.taskPrimaryTranslation.value = 0;
- simulator.taskSecondaryTranslation.value = 0;
- simulator.fullScreenProgress.value = 0;
- simulator.recentsViewScale.value = 1;
- });
- // Similar to setRunningTaskHidden below, reapply the state before runningTaskView is
- // null.
- if (!mRunningTaskShowScreenshot) {
- setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot);
- }
+ // resetTaskVisuals is called at the end of dismiss animation which could update
+ // primary and secondary translation of the live tile cut out. We will need to do so
+ // here accordingly.
+ runActionOnRemoteHandles(remoteTargetHandle -> {
+ TaskViewSimulator simulator = remoteTargetHandle.getTaskViewSimulator();
+ simulator.taskPrimaryTranslation.value = 0;
+ simulator.taskSecondaryTranslation.value = 0;
+ simulator.fullScreenProgress.value = 0;
+ simulator.recentsViewScale.value = 1;
+ });
+ // Similar to setRunningTaskHidden below, reapply the state before runningTaskView is
+ // null.
+ if (!mRunningTaskShowScreenshot) {
+ setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot);
}
if (mRunningTaskTileHidden) {
setRunningTaskHidden(mRunningTaskTileHidden);
@@ -1723,6 +1720,7 @@
// Changed orientations, update controllers so they intercept accordingly.
mActivity.getDragLayer().recreateControllers();
onOrientationChanged();
+ resetTaskVisuals();
}
boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0
@@ -2035,7 +2033,7 @@
mFocusedTaskViewId = -1;
if (mRecentsAnimationController != null) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile) {
+ if (mEnableDrawingLiveTile) {
// We are still drawing the live tile, finish it now to clean up.
finishRecentsAnimation(true /* toRecents */, null);
} else {
@@ -2274,9 +2272,6 @@
setEnableFreeScroll(true);
setEnableDrawingLiveTile(mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS);
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- setRunningTaskViewShowScreenshot(true);
- }
setRunningTaskHidden(false);
animateUpTaskIconScale();
animateActionsViewIn();
@@ -2401,12 +2396,10 @@
}
private void setRunningTaskViewShowScreenshot(boolean showScreenshot) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- mRunningTaskShowScreenshot = showScreenshot;
- TaskView runningTaskView = getRunningTaskView();
- if (runningTaskView != null) {
- runningTaskView.setShowScreenshot(mRunningTaskShowScreenshot);
- }
+ mRunningTaskShowScreenshot = showScreenshot;
+ TaskView runningTaskView = getRunningTaskView();
+ if (runningTaskView != null) {
+ runningTaskView.setShowScreenshot(mRunningTaskShowScreenshot);
}
}
@@ -2775,7 +2768,7 @@
anim.setFloat(taskView, VIEW_ALPHA, 0,
clampToProgress(isOnGridBottomRow(taskView) ? ACCEL : FINAL_FRAME, 0, 0.5f));
FloatProperty<TaskView> secondaryViewTranslate =
- taskView.getSecondaryDissmissTranslationProperty();
+ taskView.getSecondaryDismissTranslationProperty();
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
int verticalFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
@@ -2787,8 +2780,7 @@
anim.add(ObjectAnimator.ofFloat(taskView, secondaryViewTranslate,
verticalFactor * secondaryTaskDimension * 2).setDuration(duration), LINEAR, sp);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
- && taskView.isRunningTask()) {
+ if (mEnableDrawingLiveTile && taskView.isRunningTask()) {
anim.addOnFrameCallback(() -> {
runActionOnRemoteHandles(
remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
@@ -2809,7 +2801,8 @@
mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
- SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
+ SplitAnimationTimings timings =
+ AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
RectF startingTaskRect = new RectF();
safeRemoveDragLayerView(mFirstFloatingTaskView);
@@ -3026,8 +3019,7 @@
dismissTranslationInterpolationEnd
- halfAdditionalDismissTranslationOffset,
END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
- && taskView.isRunningTask()) {
+ if (mEnableDrawingLiveTile && taskView.isRunningTask()) {
anim.addOnFrameCallback(() -> {
runActionOnRemoteHandles(
remoteTargetHandle ->
@@ -3053,6 +3045,9 @@
}
}
+ SplitAnimationTimings splitTimings =
+ AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
+
int distanceFromDismissedTask = 0;
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
@@ -3095,11 +3090,31 @@
float additionalDismissDuration =
ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(
i - dismissedIndex);
- anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR,
- Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + additionalDismissDuration, 0f, 1f), 1));
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
- && child instanceof TaskView
+
+ // We are in non-grid layout.
+ // If dismissing for split select, use split timings.
+ // If not, use dismiss timings.
+ float animationStartProgress = isSplitSelectionActive()
+ ? Utilities.boundToRange(splitTimings.getGridSlideStartOffset(), 0f, 1f)
+ : Utilities.boundToRange(
+ INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ + additionalDismissDuration, 0f, 1f);
+
+ float animationEndProgress = isSplitSelectionActive()
+ ? Utilities.boundToRange(splitTimings.getGridSlideStartOffset()
+ + splitTimings.getGridSlideDurationOffset(), 0f, 1f)
+ : 1f;
+
+ // Slide tiles in horizontally to fill dismissed area
+ anim.setFloat(child, translationProperty, scrollDiff,
+ clampToProgress(
+ splitTimings.getGridSlidePrimaryInterpolator(),
+ animationStartProgress,
+ animationEndProgress
+ )
+ );
+
+ if (mEnableDrawingLiveTile && child instanceof TaskView
&& ((TaskView) child).isRunningTask()) {
anim.addOnFrameCallback(() -> {
runActionOnRemoteHandles(
@@ -3138,11 +3153,11 @@
: distanceFromDismissedTask;
// Set timings based on if user is initiating splitscreen on the focused task,
// or splitting/dismissing some other task.
- SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
float animationStartProgress = isStagingFocusedTask
? Utilities.boundToRange(
- timings.getGridSlideStartOffset()
- + (timings.getGridSlideStaggerOffset() * staggerColumn),
+ splitTimings.getGridSlideStartOffset()
+ + (splitTimings.getGridSlideStaggerOffset()
+ * staggerColumn),
0f,
dismissTranslationInterpolationEnd)
: Utilities.boundToRange(
@@ -3151,9 +3166,9 @@
* staggerColumn, 0f, dismissTranslationInterpolationEnd);
float animationEndProgress = isStagingFocusedTask
? Utilities.boundToRange(
- timings.getGridSlideStartOffset()
- + (timings.getGridSlideStaggerOffset() * staggerColumn)
- + timings.getGridSlideDurationOffset(),
+ splitTimings.getGridSlideStartOffset()
+ + (splitTimings.getGridSlideStaggerOffset() * staggerColumn)
+ + splitTimings.getGridSlideDurationOffset(),
0f,
dismissTranslationInterpolationEnd)
: dismissTranslationInterpolationEnd;
@@ -3173,7 +3188,7 @@
if (!nextFocusedTaskFromTop) {
secondaryTranslation -= mTopBottomRowHeightDiff;
}
- anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(),
+ anim.setFloat(taskView, taskView.getSecondaryDismissTranslationProperty(),
secondaryTranslation, clampToProgress(LINEAR, animationStartProgress,
dismissTranslationInterpolationEnd));
anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f,
@@ -3222,8 +3237,7 @@
mPendingAnimation.addEndListener(new Consumer<Boolean>() {
@Override
public void accept(Boolean success) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
- && dismissedTaskView.isRunningTask() && success) {
+ if (mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
() -> onEnd(success));
} else {
@@ -3240,8 +3254,7 @@
if (success) {
if (shouldRemoveTask) {
if (dismissedTaskView.getTask() != null) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()
- && dismissedTaskView.isRunningTask()) {
+ if (dismissedTaskView.isRunningTask()) {
finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
() -> removeTaskInternal(dismissedTaskViewId));
} else {
@@ -3442,10 +3455,9 @@
boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
- mActionsView.updateSplitButtonFlags(FLAG_IS_NOT_TABLET,
+ mActionsView.updateSplitButtonHiddenFlags(FLAG_IS_NOT_TABLET,
!mActivity.getDeviceProfile().isTablet);
- mActionsView.updateSplitButtonFlags(FLAG_SINGLE_TASK, getTaskViewCount() <= 1);
- mActionsView.updateSplitButtonVisibility();
+ mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK, getTaskViewCount() <= 1);
}
/**
@@ -3900,8 +3912,7 @@
? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
: mOrientationHandler.getPrimaryViewTranslate();
translationProperty.set(child, totalTranslation);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile
- && i == getRunningTaskIndex()) {
+ if (mEnableDrawingLiveTile && i == getRunningTaskIndex()) {
runActionOnRemoteHandles(
remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
.taskPrimaryTranslation.value = totalTranslation);
@@ -4125,12 +4136,13 @@
mSplitSelectStateController.setInitialTaskSelect(taskView.getTask().key.id,
stagePosition, splitEvent, taskView.getItemInfo());
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
- null /* onFinishComplete */);
- }
+ finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+ null /* onFinishComplete */);
}
+ /**
+ * Called when staging a split from Home/AllApps, using the icon long-press menu.
+ */
public void initiateSplitSelect(QuickstepSystemShortcut.SplitSelectSource splitSelectSource) {
mSplitSelectSource = splitSelectSource;
mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
@@ -4179,9 +4191,13 @@
// TODO(194414938) starting bounds seem slightly off, investigate
Rect firstTaskStartingBounds = new Rect();
Rect firstTaskEndingBounds = mTempRect;
- PendingAnimation pendingAnimation =
- new PendingAnimation(SplitAnimationTimings.CONFIRM_DURATION);
- SplitAnimationTimings timings = SplitAnimationTimings.SPLIT_TO_CONFIRM;
+
+ boolean isTablet = mActivity.getDeviceProfile().isTablet;
+ int duration = isTablet
+ ? SplitAnimationTimings.TABLET_CONFIRM_DURATION
+ : SplitAnimationTimings.PHONE_CONFIRM_DURATION;
+ PendingAnimation pendingAnimation = new PendingAnimation(duration);
+ SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
int halfDividerSize = getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
@@ -4257,8 +4273,18 @@
snapToPageImmediately(pageToSnapTo);
}
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
+
+ // We are leaving split selection state, so it is safe to reset thumbnail translations for
+ // the next time split is invoked.
+ setTaskViewsPrimarySplitTranslation(0);
+ setTaskViewsSecondarySplitTranslation(0);
+
resetTaskVisuals();
mSplitHiddenTaskViewIndex = -1;
+ if (mSplitHiddenTaskView != null) {
+ mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE);
+ mSplitHiddenTaskView = null;
+ }
}
private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
@@ -4398,9 +4424,7 @@
anim.play(ObjectAnimator.ofFloat(getPageAt(centerTaskIndex),
mOrientationHandler.getPrimaryViewTranslate(), primaryTranslation));
int runningTaskIndex = getRunningTaskIndex();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()
- && runningTaskIndex != -1
- && runningTaskIndex != taskIndex
+ if (runningTaskIndex != -1 && runningTaskIndex != taskIndex
&& getRemoteTargetHandles() != null) {
for (RemoteTargetHandle remoteHandle : getRemoteTargetHandles()) {
anim.play(ObjectAnimator.ofFloat(
@@ -4489,12 +4513,10 @@
mPendingAnimation = new PendingAnimation(duration);
mPendingAnimation.add(anim);
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- runActionOnRemoteHandles(
- remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
- .addOverviewToAppAnim(mPendingAnimation, interpolator));
- mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
- }
+ runActionOnRemoteHandles(
+ remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator()
+ .addOverviewToAppAnim(mPendingAnimation, interpolator));
+ mPendingAnimation.addOnFrameCallback(this::redrawLiveTile);
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
if (tv.getTaskIds()[1] != -1 && mRemoteTargetHandles != null) {
@@ -4506,7 +4528,7 @@
dividerAnimator.end();
});
}
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && tv.isRunningTask()) {
+ if (tv.isRunningTask()) {
finishRecentsAnimation(false /* toRecents */, null);
onTaskLaunchAnimationEnd(true /* success */);
} else {
@@ -4679,7 +4701,7 @@
if (sendUserLeaveHint) {
// Notify the SysUI to use fade-in animation when entering PiP from live tile.
final SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(getContext());
- systemUiProxy.notifySwipeToHomeFinished();
+ systemUiProxy.setPipAnimationTypeToAlpha();
systemUiProxy.setShelfHeight(true, mActivity.getDeviceProfile().hotseatBarSizePx);
// Transaction to hide the task to avoid flicker for entering PiP from split-screen.
// See also {@link AbsSwipeUpHandler#maybeFinishSwipeToHome}.
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index d7a8599..04a0af1 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -16,11 +16,11 @@
package com.android.quickstep.views;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
+import static com.android.systemui.shared.recents.utilities.PreviewPositionHelper.MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT;
+import static com.android.systemui.shared.recents.utilities.Utilities.isRelativePercentDifferenceGreaterThan;
import android.content.Context;
import android.graphics.Bitmap;
@@ -41,7 +41,6 @@
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Property;
-import android.view.Surface;
import android.view.View;
import android.widget.ImageView;
@@ -60,6 +59,7 @@
import com.android.quickstep.views.TaskView.FullscreenDrawParams;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
/**
* A task in the Recents view.
@@ -67,7 +67,6 @@
public class TaskThumbnailView extends View {
private static final MainThreadInitializedObject<FullscreenDrawParams> TEMP_PARAMS =
new MainThreadInitializedObject<>(FullscreenDrawParams::new);
- private static final float MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT = 0.1f;
public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
new FloatProperty<TaskThumbnailView>("dimAlpha") {
@@ -320,13 +319,11 @@
public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height,
float cornerRadius) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
- canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
- canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
- mDimmingPaintAfterClearing);
- return;
- }
+ if (mTask != null && getTaskView().isRunningTask() && !getTaskView().showScreenshot()) {
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mClearPaint);
+ canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius,
+ mDimmingPaintAfterClearing);
+ return;
}
// Always draw the background since the snapshots might be translucent or partially empty
@@ -421,7 +418,7 @@
float thumbnailDataAspect =
mThumbnailData.thumbnail.getWidth() / (float) mThumbnailData.thumbnail.getHeight();
- return Utilities.isRelativePercentDifferenceGreaterThan(thumbnailViewAspect,
+ return isRelativePercentDifferenceGreaterThan(thumbnailViewAspect,
thumbnailDataAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT);
}
@@ -445,8 +442,8 @@
*/
private void refreshOverlay() {
if (mOverlayEnabled) {
- getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.mMatrix,
- mPreviewPositionHelper.mIsOrientationChanged);
+ getTaskOverlay().initOverlay(mTask, mThumbnailData, mPreviewPositionHelper.getMatrix(),
+ mPreviewPositionHelper.isOrientationChanged());
} else {
getTaskOverlay().reset();
}
@@ -467,18 +464,19 @@
}
private void updateThumbnailMatrix() {
- mPreviewPositionHelper.mIsOrientationChanged = false;
+ mPreviewPositionHelper.setOrientationChanged(false);
if (mBitmapShader != null && mThumbnailData != null) {
mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
mThumbnailData.thumbnail.getHeight());
int currentRotation = getTaskView().getRecentsView().getPagedViewOrientedState()
.getRecentsActivityRotation();
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ DeviceProfile dp = mActivity.getDeviceProfile();
mPreviewPositionHelper.updateThumbnailMatrix(mPreviewRect, mThumbnailData,
- getMeasuredWidth(), getMeasuredHeight(), mActivity.getDeviceProfile(),
- currentRotation, isRtl);
+ getMeasuredWidth(), getMeasuredHeight(), dp.widthPx, dp.taskbarSize,
+ dp.isTablet, currentRotation, isRtl);
- mBitmapShader.setLocalMatrix(mPreviewPositionHelper.mMatrix);
+ mBitmapShader.setLocalMatrix(mPreviewPositionHelper.getMatrix());
mPaint.setShader(mBitmapShader);
}
getTaskView().updateCurrentFullscreenParams(mPreviewPositionHelper);
@@ -518,199 +516,4 @@
}
return mThumbnailData.isRealSnapshot && !mTask.isLocked;
}
-
- /**
- * Utility class to position the thumbnail in the TaskView
- */
- public static class PreviewPositionHelper {
-
- private static final RectF EMPTY_RECT_F = new RectF();
-
- // Contains the portion of the thumbnail that is unclipped when fullscreen progress = 1.
- private final RectF mClippedInsets = new RectF();
- private final Matrix mMatrix = new Matrix();
- private boolean mIsOrientationChanged;
-
- public Matrix getMatrix() {
- return mMatrix;
- }
-
- /**
- * Updates the matrix based on the provided parameters
- */
- public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
- int canvasWidth, int canvasHeight, DeviceProfile dp, int currentRotation,
- boolean isRtl) {
- boolean isRotated = false;
- boolean isOrientationDifferent;
-
- int thumbnailRotation = thumbnailData.rotation;
- int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation);
- RectF thumbnailClipHint = new RectF();
- float canvasScreenRatio = canvasWidth / (float) dp.widthPx;
- float scaledTaskbarSize = dp.taskbarSize * canvasScreenRatio;
- thumbnailClipHint.bottom = dp.isTablet ? scaledTaskbarSize : 0;
-
- float scale = thumbnailData.scale;
- final float thumbnailScale;
-
- // Landscape vs portrait change.
- // Note: Disable rotation in grid layout.
- boolean windowingModeSupportsRotation =
- thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !dp.isTablet;
- isOrientationDifferent = isOrientationChange(deltaRotate)
- && windowingModeSupportsRotation;
- if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
- // If we haven't measured , skip the thumbnail drawing and only draw the background
- // color
- thumbnailScale = 0f;
- } else {
- // Rotate the screenshot if not in multi-window mode
- isRotated = deltaRotate > 0 && windowingModeSupportsRotation;
-
- float surfaceWidth = thumbnailBounds.width() / scale;
- float surfaceHeight = thumbnailBounds.height() / scale;
- float availableWidth = surfaceWidth
- - (thumbnailClipHint.left + thumbnailClipHint.right);
- float availableHeight = surfaceHeight
- - (thumbnailClipHint.top + thumbnailClipHint.bottom);
-
- float canvasAspect = canvasWidth / (float) canvasHeight;
- float availableAspect = isRotated
- ? availableHeight / availableWidth
- : availableWidth / availableHeight;
- boolean isAspectLargelyDifferent =
- Utilities.isRelativePercentDifferenceGreaterThan(canvasAspect,
- availableAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT);
- if (isRotated && isAspectLargelyDifferent) {
- // Do not rotate thumbnail if it would not improve fit
- isRotated = false;
- isOrientationDifferent = false;
- }
-
- if (isAspectLargelyDifferent) {
- // Crop letterbox insets if insets isn't already clipped
- thumbnailClipHint.left = thumbnailData.letterboxInsets.left;
- thumbnailClipHint.right = thumbnailData.letterboxInsets.right;
- thumbnailClipHint.top = thumbnailData.letterboxInsets.top;
- thumbnailClipHint.bottom = thumbnailData.letterboxInsets.bottom;
- availableWidth = surfaceWidth
- - (thumbnailClipHint.left + thumbnailClipHint.right);
- availableHeight = surfaceHeight
- - (thumbnailClipHint.top + thumbnailClipHint.bottom);
- }
-
- final float targetW, targetH;
- if (isOrientationDifferent) {
- targetW = canvasHeight;
- targetH = canvasWidth;
- } else {
- targetW = canvasWidth;
- targetH = canvasHeight;
- }
- float targetAspect = targetW / targetH;
-
- // Update the clipHint such that
- // > the final clipped position has same aspect ratio as requested by canvas
- // > first fit the width and crop the extra height
- // > if that will leave empty space, fit the height and crop the width instead
- float croppedWidth = availableWidth;
- float croppedHeight = croppedWidth / targetAspect;
- if (croppedHeight > availableHeight) {
- croppedHeight = availableHeight;
- if (croppedHeight < targetH) {
- croppedHeight = Math.min(targetH, surfaceHeight);
- }
- croppedWidth = croppedHeight * targetAspect;
-
- // One last check in case the task aspect radio messed up something
- if (croppedWidth > surfaceWidth) {
- croppedWidth = surfaceWidth;
- croppedHeight = croppedWidth / targetAspect;
- }
- }
-
- // Update the clip hints. Align to 0,0, crop the remaining.
- if (isRtl) {
- thumbnailClipHint.left += availableWidth - croppedWidth;
- if (thumbnailClipHint.right < 0) {
- thumbnailClipHint.left += thumbnailClipHint.right;
- thumbnailClipHint.right = 0;
- }
- } else {
- thumbnailClipHint.right += availableWidth - croppedWidth;
- if (thumbnailClipHint.left < 0) {
- thumbnailClipHint.right += thumbnailClipHint.left;
- thumbnailClipHint.left = 0;
- }
- }
- thumbnailClipHint.bottom += availableHeight - croppedHeight;
- if (thumbnailClipHint.top < 0) {
- thumbnailClipHint.bottom += thumbnailClipHint.top;
- thumbnailClipHint.top = 0;
- } else if (thumbnailClipHint.bottom < 0) {
- thumbnailClipHint.top += thumbnailClipHint.bottom;
- thumbnailClipHint.bottom = 0;
- }
-
- thumbnailScale = targetW / (croppedWidth * scale);
- }
-
- if (!isRotated) {
- mMatrix.setTranslate(
- -thumbnailClipHint.left * scale,
- -thumbnailClipHint.top * scale);
- } else {
- setThumbnailRotation(deltaRotate, thumbnailBounds);
- }
-
- mClippedInsets.set(0, 0, 0, scaledTaskbarSize);
-
- mMatrix.postScale(thumbnailScale, thumbnailScale);
- mIsOrientationChanged = isOrientationDifferent;
- }
-
- private int getRotationDelta(int oldRotation, int newRotation) {
- int delta = newRotation - oldRotation;
- if (delta < 0) delta += 4;
- return delta;
- }
-
- /**
- * @param deltaRotation the number of 90 degree turns from the current orientation
- * @return {@code true} if the change in rotation results in a shift from landscape to
- * portrait or vice versa, {@code false} otherwise
- */
- private boolean isOrientationChange(int deltaRotation) {
- return deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270;
- }
-
- private void setThumbnailRotation(int deltaRotate, Rect thumbnailPosition) {
- float translateX = 0;
- float translateY = 0;
-
- mMatrix.setRotate(90 * deltaRotate);
- switch (deltaRotate) { /* Counter-clockwise */
- case Surface.ROTATION_90:
- translateX = thumbnailPosition.height();
- break;
- case Surface.ROTATION_270:
- translateY = thumbnailPosition.width();
- break;
- case Surface.ROTATION_180:
- translateX = thumbnailPosition.width();
- translateY = thumbnailPosition.height();
- break;
- }
- mMatrix.postTranslate(translateX, translateY);
- }
-
- /**
- * Insets to used for clipping the thumbnail (in case it is drawing outside its own space)
- */
- public RectF getInsetsToDrawInFullscreen(DeviceProfile dp) {
- return dp.isTaskbarPresent && !dp.isTaskbarPresentInApps
- ? mClippedInsets : EMPTY_RECT_F;
- }
- }
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index a81f95f..0125775 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -25,7 +25,6 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
@@ -88,6 +87,7 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
+import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
@@ -98,9 +98,9 @@
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.TaskCornerRadius;
import com.android.quickstep.util.TransformParams;
-import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -121,6 +121,8 @@
private static final String TAG = TaskView.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final RectF EMPTY_RECT_F = new RectF();
+
public static final int FLAG_UPDATE_ICON = 1;
public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
@@ -625,7 +627,7 @@
if (ActivityManagerWrapper.getInstance()
.startActivityFromRecents(mTask.key, opts.options)) {
RecentsView recentsView = getRecentsView();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && recentsView.getRunningTaskViewId() != -1) {
+ if (recentsView.getRunningTaskViewId() != -1) {
recentsView.onTaskLaunchedInLiveTileMode();
// Return a fresh callback in the live tile case, so that it's not accidentally
@@ -708,7 +710,12 @@
RecentsView recentsView = getRecentsView();
RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
RunnableList runnableList = new RunnableList();
- if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask() && remoteTargetHandles != null) {
+ if (mTask != null && mTask.desktopTile) {
+ // clicked on desktop
+ SystemUiProxy.INSTANCE.get(getContext()).showDesktopApps();
+ return runnableList;
+ }
+ if (isRunningTask() && remoteTargetHandles != null) {
if (!mIsClickableAsLiveTile) {
return runnableList;
}
@@ -1255,7 +1262,7 @@
DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
}
- public FloatProperty<TaskView> getSecondaryDissmissTranslationProperty() {
+ public FloatProperty<TaskView> getSecondaryDismissTranslationProperty() {
return getPagedOrientationHandler().getSecondaryValue(
DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
}
@@ -1567,7 +1574,7 @@
*/
public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale,
int previewWidth, DeviceProfile dp, PreviewPositionHelper pph) {
- RectF insets = pph.getInsetsToDrawInFullscreen(dp);
+ RectF insets = getInsetsToDrawInFullscreen(pph, dp);
float currentInsetsLeft = insets.left * fullscreenProgress;
float currentInsetsTop = insets.top * fullscreenProgress;
@@ -1586,6 +1593,14 @@
mScale = previewWidth / (previewWidth + currentInsetsLeft + currentInsetsRight);
}
}
+
+ /**
+ * Insets to used for clipping the thumbnail (in case it is drawing outside its own space)
+ */
+ private static RectF getInsetsToDrawInFullscreen(PreviewPositionHelper pph, DeviceProfile dp) {
+ return dp.isTaskbarPresent && !dp.isTaskbarPresentInApps
+ ? pph.getClippedInsets() : EMPTY_RECT_F;
+ }
}
public class TaskIdAttributeContainer {
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index f190e27..e2774c0 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -16,8 +16,6 @@
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-
import static org.junit.Assert.assertTrue;
import android.os.SystemProperties;
@@ -79,8 +77,7 @@
private boolean isInLiveTileMode(Launcher launcher,
LauncherInstrumentation.ContainerType expectedContainerType) {
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get()
- || expectedContainerType != LauncherInstrumentation.ContainerType.OVERVIEW) {
+ if (expectedContainerType != LauncherInstrumentation.ContainerType.OVERVIEW) {
return false;
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaskThumbnailViewTest.kt b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
similarity index 64%
rename from quickstep/tests/src/com/android/quickstep/TaskThumbnailViewTest.kt
rename to quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index cf3c8c9..4785350 100644
--- a/quickstep/tests/src/com/android/quickstep/TaskThumbnailViewTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -20,26 +20,34 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.DeviceProfileBaseTest
-import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper
+import com.android.quickstep.views.TaskView.FullscreenDrawParams
import com.android.systemui.shared.recents.model.ThumbnailData
+import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
import com.google.common.truth.Truth.assertThat
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
/**
- * Test for TaskThumbnailView class.
+ * Test for FullscreenDrawParams class.
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
-class TaskThumbnailViewTest : DeviceProfileBaseTest() {
+class FullscreenDrawParamsTest : DeviceProfileBaseTest() {
private var mThumbnailData: ThumbnailData = mock(ThumbnailData::class.java)
private val mPreviewPositionHelper = PreviewPositionHelper()
+ private lateinit var params: FullscreenDrawParams
+
+ @Before
+ fun setup() {
+ params = FullscreenDrawParams(context)
+ }
@Test
- fun getInsetsToDrawInFullscreen_clipTaskbarSizeFromBottomForTablets() {
+ fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromBottomForTablets() {
initializeVarsForTablet()
val dp = newDP()
val previewRect = Rect(0, 0, 100, 100)
@@ -49,15 +57,18 @@
val isRtl = false
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
- canvasHeight, dp, currentRotation, isRtl)
+ canvasHeight, dp.widthPx, dp.taskbarSize, dp.isTablet, currentRotation,
+ isRtl)
+ params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
val expectedClippedInsets = RectF(0f, 0f, 0f, dp.taskbarSize / 2f)
- assertThat(mPreviewPositionHelper.getInsetsToDrawInFullscreen(dp))
+ assertThat(params.mCurrentDrawnInsets)
.isEqualTo(expectedClippedInsets)
}
@Test
- fun getInsetsToDrawInFullscreen_doNotClipTaskbarSizeFromBottomForPhones() {
+ fun setFullProgress_currentDrawnInsets_doNotClipTaskbarSizeFromBottomForPhones() {
initializeVarsForPhone()
val dp = newDP()
val previewRect = Rect(0, 0, 100, 100)
@@ -67,10 +78,13 @@
val isRtl = false
mPreviewPositionHelper.updateThumbnailMatrix(previewRect, mThumbnailData, canvasWidth,
- canvasHeight, dp, currentRotation, isRtl)
+ canvasHeight, dp.widthPx, dp.taskbarSize, dp.isTablet, currentRotation,
+ isRtl)
+ params.setProgress(/* fullscreenProgress= */ 1.0f, /* parentScale= */ 1.0f,
+ /* taskViewScale= */ 1.0f, /* previewWidth= */ 0, dp, mPreviewPositionHelper)
val expectedClippedInsets = RectF(0f, 0f, 0f, 0f)
- assertThat(mPreviewPositionHelper.getInsetsToDrawInFullscreen(dp))
+ assertThat(params.mCurrentDrawnInsets)
.isEqualTo(expectedClippedInsets)
}
}
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 42e9be3..cc561c6 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -309,6 +309,28 @@
launchedAppState.switchToOverview();
}
+ @Test
+ @ScreenRecord // b/242163205
+ public void testQuickSwitchToPreviousAppForTablet() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+ startTestActivity(2);
+ startImeTestActivity();
+
+ // Set ignoreTaskbarVisibility to true to verify the task bar visibility explicitly.
+ mLauncher.setIgnoreTaskbarVisibility(true);
+
+ // Expect task bar invisible when the launched app was the IME activity.
+ LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
+ launchedAppState.assertTaskbarHidden();
+
+ // Quick-switch to the test app with swiping to right.
+ launchedAppState.quickSwitchToPreviousApp();
+
+ // Expect task bar visible when the launched app was the test activity.
+ launchedAppState = getAndAssertLaunchedApp();
+ launchedAppState.assertTaskbarVisible();
+ }
+
private boolean isTestActivityRunning(int activityNumber) {
return mDevice.wait(Until.hasObject(By.pkg(getAppPackageName())
.text("TestActivity" + activityNumber)),
diff --git a/res/drawable/page_indicator.xml b/res/drawable/page_indicator.xml
new file mode 100644
index 0000000..c0ccc49
--- /dev/null
+++ b/res/drawable/page_indicator.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="?attr/folderPaginationColor"/>
+ <size android:width="@dimen/page_indicator_size" android:height="@dimen/page_indicator_size"/>
+</shape>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5dae9f2..47584e2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -248,7 +248,7 @@
<!-- Folders -->
<dimen name="page_indicator_dot_size">8dp</dimen>
- <dimen name="page_indicator_current_page_indicator_size">10dp</dimen>
+ <dimen name="page_indicator_size">10dp</dimen>
<dimen name="folder_cell_x_padding">9dp</dimen>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 4cad919..9a1bba9 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -43,6 +43,7 @@
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.DevicePaddings.DevicePadding;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.IconNormalizer;
import com.android.launcher3.model.data.ItemInfo;
@@ -1276,7 +1277,10 @@
return ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
}
- return isTaskbarPresent ? stashedTaskbarSize : mInsets.bottom;
+ if (isTaskbarPresent) {
+ return FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get() ? taskbarSize : stashedTaskbarSize;
+ }
+ return mInsets.bottom;
}
/** Gets the space that the overview actions will take, including bottom margin. */
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 616b08a..f70511a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -819,16 +819,6 @@
}
/**
- * Compares the ratio of two quantities and returns whether that ratio is greater than the
- * provided bound. Order of quantities does not matter. Bound should be a decimal representation
- * of a percentage.
- */
- public static boolean isRelativePercentDifferenceGreaterThan(float first, float second,
- float bound) {
- return (Math.abs(first - second) / Math.abs((first + second) / 2.0f)) > bound;
- }
-
- /**
* Rotates `inOutBounds` by `delta` 90-degree increments. Rotation is visually CCW. Parent
* sizes represent the "space" that will rotate carrying inOutBounds along with it to determine
* the final bounds.
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index e0b4951..368a373 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -42,25 +42,29 @@
BaseAllAppsAdapter<T> {
public static final String TAG = "AppsGridAdapter";
- private final GridLayoutManager mGridLayoutMgr;
- private final GridSpanSizer mGridSizer;
+ private final AppsGridLayoutManager mGridLayoutMgr;
public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
super(activityContext, inflater, apps, adapterProviders);
- mGridSizer = new GridSpanSizer();
mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
- mGridLayoutMgr.setSpanSizeLookup(mGridSizer);
+ mGridLayoutMgr.setSpanSizeLookup(new GridSpanSizer());
setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns);
}
/**
* Returns the grid layout manager.
*/
- public RecyclerView.LayoutManager getLayoutManager() {
+ public AppsGridLayoutManager getLayoutManager() {
return mGridLayoutMgr;
}
+ /** @return the column index that the given adapter index falls. */
+ public int getSpanIndex(int adapterIndex) {
+ AppsGridLayoutManager lm = getLayoutManager();
+ return lm.getSpanSizeLookup().getSpanIndex(adapterIndex, lm.getSpanCount());
+ }
+
/**
* A subclass of GridLayoutManager that overrides accessibility values during app search.
*/
diff --git a/src/com/android/launcher3/allapps/SearchTransitionController.java b/src/com/android/launcher3/allapps/SearchTransitionController.java
index 8fc7965..a1f5bc6 100644
--- a/src/com/android/launcher3/allapps/SearchTransitionController.java
+++ b/src/com/android/launcher3/allapps/SearchTransitionController.java
@@ -29,6 +29,7 @@
import android.animation.ObjectAnimator;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
+import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
@@ -36,10 +37,13 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
/** Coordinates the transition between Search and A-Z in All Apps. */
public class SearchTransitionController {
+ private static final String LOG_TAG = "SearchTransitionCtrl";
+
// Interpolator when the user taps the QSB while already in All Apps.
private static final Interpolator INTERPOLATOR_WITHIN_ALL_APPS = DEACCEL_1_7;
// Interpolator when the user taps the QSB from home screen, so transition to all apps is
@@ -171,6 +175,7 @@
int appRowHeight = 0;
Integer top = null;
SearchRecyclerView searchRecyclerView = getSearchRecyclerView();
+
for (int i = 0; i < searchRecyclerView.getChildCount(); i++) {
View searchResultView = searchRecyclerView.getChildAt(i);
if (searchResultView == null) {
@@ -226,15 +231,43 @@
float scaleY = 1 - mSearchToAzProgress;
int scaledHeight = (int) (searchResultView.getHeight() * scaleY);
searchResultView.setScaleY(scaleY);
- searchResultView.setY(top + totalHeight);
- numSearchResultsAnimated++;
- totalHeight += scaledHeight;
+ // For rows with multiple elements, only count the height once and translate elements to
+ // the same y position.
+ int y = top + totalHeight;
+ int spanIndex = getSpanIndex(searchRecyclerView, adapterPosition);
+ if (spanIndex > 0) {
+ // Continuation of an existing row; move this item into the row.
+ y -= scaledHeight;
+ } else {
+ // Start of a new row contributes to total height and animation stagger.
+ numSearchResultsAnimated++;
+ totalHeight += scaledHeight;
+ }
+ searchResultView.setY(y);
}
return totalHeight - appRowHeight;
}
+ /** @return the column that the view at this position is found (0 assumed if indeterminate). */
+ private int getSpanIndex(SearchRecyclerView searchRecyclerView, int adapterPosition) {
+ if (adapterPosition == NO_POSITION) {
+ Log.w(LOG_TAG, "Can't determine span index - child not found in adapter");
+ return 0;
+ }
+ if (!(searchRecyclerView.getAdapter() instanceof AllAppsGridAdapter<?>)) {
+ Log.e(LOG_TAG, "Search RV doesn't have an AllAppsGridAdapter?");
+ // This case shouldn't happen, but for debug devices we will continue to create a more
+ // visible crash.
+ if (!Utilities.IS_DEBUG_DEVICE) {
+ return 0;
+ }
+ }
+ AllAppsGridAdapter<?> adapter = (AllAppsGridAdapter<?>) searchRecyclerView.getAdapter();
+ return adapter.getSpanIndex(adapterPosition);
+ }
+
/** Called just before a child is attached to the SearchRecyclerView. */
private void onSearchChildAttached(View child) {
// Avoid allocating hardware layers for alpha changes.
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 4a47e98..a2d9dd4 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -84,9 +84,6 @@
public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
"KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
- public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
- "ENABLE_QUICKSTEP_LIVE_TILE", true, "Enable live tile in Quickstep overview");
-
public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag(
"ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
@@ -97,6 +94,9 @@
public static final BooleanFlag ENABLE_HIDE_HEADER = new DeviceFlag("ENABLE_HIDE_HEADER",
true, "Hide header on keyboard before typing in all apps");
+ public static final BooleanFlag ENABLE_HIDE_HEADER_STATIC = new DeviceFlag(
+ "ENABLE_HIDE_HEADER_STATIC", false, "Hide keyboard suggestion strip");
+
public static final BooleanFlag COLLECT_SEARCH_HISTORY = new DeviceFlag(
"COLLECT_SEARCH_HISTORY", false, "Allow launcher to collect search history for log");
@@ -235,6 +235,10 @@
"ENABLE_ALL_APPS_ONE_SEARCH_IN_TASKBAR", false,
"Enables One Search box in Taskbar All Apps.");
+ public static final BooleanFlag ENABLE_TASKBAR_IN_OVERVIEW = getDebugFlag(
+ "ENABLE_TASKBAR_IN_OVERVIEW", false,
+ "Enables accessing the system Taskbar in overview.");
+
public static final BooleanFlag ENABLE_SPLIT_FROM_WORKSPACE = getDebugFlag(
"ENABLE_SPLIT_FROM_WORKSPACE", true,
"Enable initiating split screen from workspace.");
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 439e1c7..b4cb0ee 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -30,6 +30,7 @@
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Property;
import android.view.View;
@@ -56,8 +57,8 @@
private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
private static final int ENTER_ANIMATION_DURATION = 400;
- private static final int DOT_ACTIVE_ALPHA = 255;
- private static final int DOT_INACTIVE_ALPHA = 128;
+ private static final int PAGE_INDICATOR_ALPHA = 255;
+ private static final int DOT_ALPHA = 128;
private static final int DOT_GAP_FACTOR = 3;
private static final float DOT_GAP_FACTOR_FLOAT = 3.8f;
@@ -84,9 +85,11 @@
};
private final Paint mPaginationPaint;
+ private final Drawable mPageIndicatorDrawable;
private final float mDotRadius;
private final float mCircleGap;
private final float mPageIndicatorSize;
+ private final float mPageIndicatorRadius;
private final boolean mIsRtl;
private int mNumPages;
@@ -125,13 +128,22 @@
mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.folderPaginationColor));
mDotRadius = getResources().getDimension(R.dimen.page_indicator_dot_size) / 2;
+
if (SHOW_DELIGHTFUL_PAGINATION_FOLDER.get()) {
+ mPageIndicatorSize = getResources().getDimension(
+ R.dimen.page_indicator_size);
+ mPageIndicatorRadius = mPageIndicatorSize / 2;
+ mPageIndicatorDrawable = context.getDrawable(R.drawable.page_indicator);
+ mPageIndicatorDrawable.setBounds(0, 0, (int) mPageIndicatorSize,
+ (int) mPageIndicatorSize);
mCircleGap = DOT_GAP_FACTOR_FLOAT * mDotRadius;
+
} else {
+ mPageIndicatorSize = 0;
+ mPageIndicatorRadius = 0;
+ mPageIndicatorDrawable = null;
mCircleGap = DOT_GAP_FACTOR * mDotRadius;
}
- mPageIndicatorSize = getResources().getDimension(
- R.dimen.page_indicator_current_page_indicator_size);
if (!SHOW_DELIGHTFUL_PAGINATION_FOLDER.get()) {
setOutlineProvider(new MyOutlineProver());
}
@@ -141,6 +153,7 @@
@Override
public void setScroll(int currentScroll, int totalScroll) {
if (mNumPages <= 1) {
+ mCurrentScroll = 0;
return;
}
@@ -282,10 +295,14 @@
circleGap = -circleGap;
}
for (int i = 0; i < mEntryAnimationRadiusFactors.length; i++) {
- mPaginationPaint.setAlpha(i == mActivePage ? DOT_ACTIVE_ALPHA : DOT_INACTIVE_ALPHA);
+ mPaginationPaint.setAlpha(i == mActivePage ? PAGE_INDICATOR_ALPHA : DOT_ALPHA);
if (SHOW_DELIGHTFUL_PAGINATION_FOLDER.get()) {
- canvas.drawCircle(x, y, getRadius(x) * mEntryAnimationRadiusFactors[i],
- mPaginationPaint);
+ if (i != mActivePage) {
+ canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i],
+ mPaginationPaint);
+ } else {
+ drawPageIndicator(canvas, mEntryAnimationRadiusFactors[i]);
+ }
} else {
canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i],
mPaginationPaint);
@@ -293,7 +310,8 @@
x += circleGap;
}
} else {
- mPaginationPaint.setAlpha(DOT_INACTIVE_ALPHA);
+ // Here we draw the dots
+ mPaginationPaint.setAlpha(DOT_ALPHA);
for (int i = 0; i < mNumPages; i++) {
if (SHOW_DELIGHTFUL_PAGINATION_FOLDER.get()) {
canvas.drawCircle(x, y, getRadius(x), mPaginationPaint);
@@ -303,20 +321,10 @@
x += circleGap;
}
- mPaginationPaint.setAlpha(DOT_ACTIVE_ALPHA);
-
+ // Here we draw the current page indicator
+ mPaginationPaint.setAlpha(PAGE_INDICATOR_ALPHA);
if (SHOW_DELIGHTFUL_PAGINATION_FOLDER.get()) {
- RectF currRect = getActiveRect();
- int scrollPerPage = getScrollPerPage();
-
- // This IF is to avoid division by 0
- if (scrollPerPage != 0) {
- int delta = mCurrentScroll % scrollPerPage;
- canvas.rotate((INDICATOR_ROTATION * delta) / scrollPerPage,
- currRect.centerX(), currRect.centerY());
- }
-
- canvas.drawRect(currRect, mPaginationPaint);
+ drawPageIndicator(canvas, 1);
} else {
canvas.drawRoundRect(getActiveRect(), mDotRadius, mDotRadius, mPaginationPaint);
}
@@ -324,6 +332,36 @@
}
/**
+ * Draws the page indicator, denoting the currently selected page
+ *
+ * @param canvas is used to draw the page indicator and to rotate it as we scroll
+ * @param scale is used to set the scale of our canvas
+ */
+ private void drawPageIndicator(Canvas canvas, float scale) {
+ RectF currRect = getActiveRect();
+
+ // saves the canvas so we can later restore it to its original scale
+ canvas.save();
+
+ // Moves the canvas to start at the top left corner of the page indicator
+ canvas.translate(currRect.left, currRect.top);
+
+ // Scales the canvas in place to animate the indicator on entry
+ canvas.scale(scale, scale, mPageIndicatorRadius, mPageIndicatorRadius);
+
+ int scrollPerPage = getScrollPerPage();
+ // This IF is to avoid division by 0
+ if (scrollPerPage != 0) {
+ int delta = mCurrentScroll % scrollPerPage;
+ canvas.rotate((INDICATOR_ROTATION * delta) / scrollPerPage,
+ mPageIndicatorRadius, mPageIndicatorRadius);
+ }
+
+ mPageIndicatorDrawable.draw(canvas);
+ canvas.restore();
+ }
+
+ /**
* Returns the radius of the circle based on how close the page indicator is to it
*
* @param dotPositionX is the position the dot is located at in the x-axis
@@ -333,7 +371,7 @@
float startXIndicator =
((getWidth() - (mNumPages * mCircleGap) + mDotRadius) / 2) - getOffset();
float indicatorPosition = startXIndicator + getIndicatorScrollDistance()
- + (mPageIndicatorSize / 2);
+ + mPageIndicatorRadius;
// If the indicator gets close enough to a dot then we change the radius
// of the dot based on how close the indicator is to it.
@@ -390,7 +428,7 @@
* the indicator is centered in with the indicator circles
*/
private float getOffset() {
- return (mPageIndicatorSize / 2) - mDotRadius;
+ return mPageIndicatorRadius - mDotRadius;
}
/**
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 47503b1..f73347a 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -33,6 +33,8 @@
import android.view.ViewGroup;
import android.view.animation.Interpolator;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
@@ -41,6 +43,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Extension of {@link AbstractFloatingView} with common methods for sliding in from bottom.
@@ -79,6 +82,7 @@
protected float mTranslationShift = TRANSLATION_SHIFT_CLOSED;
protected boolean mNoIntercept;
+ protected @Nullable OnCloseListener mOnCloseBeginListener;
protected List<OnCloseListener> mOnCloseListeners = new ArrayList<>();
public AbstractSlideInView(Context context, AttributeSet attrs, int defStyleAttr) {
@@ -204,6 +208,11 @@
}
}
+ /** Callback invoked when the view is beginning to close (e.g. close animation is started). */
+ public void setOnCloseBeginListener(@Nullable OnCloseListener onCloseBeginListener) {
+ mOnCloseBeginListener = onCloseBeginListener;
+ }
+
/** Registers an {@link OnCloseListener}. */
public void addOnCloseListener(OnCloseListener listener) {
mOnCloseListeners.add(listener);
@@ -213,6 +222,8 @@
if (!mIsOpen) {
return;
}
+ Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
+
if (!animate) {
mOpenCloseAnimator.cancel();
setTranslationShift(TRANSLATION_SHIFT_CLOSED);
diff --git a/tests/Android.bp b/tests/Android.bp
index 1584308..39bd307 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -60,6 +60,7 @@
"src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
"src/com/android/launcher3/testcomponent/TestCommandReceiver.java",
"src/com/android/launcher3/testcomponent/TestLauncherActivity.java",
+ "src/com/android/launcher3/testcomponent/ImeTestActivity.java",
],
}
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 9cc3aed..ae1060e 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -277,6 +277,16 @@
</intent-filter>
</activity-alias>
+ <activity android:name="com.android.launcher3.testcomponent.ImeTestActivity"
+ android:label="ImeTestActivity"
+ android:icon="@drawable/test_theme_icon"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
<!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
<provider
android:name="androidx.startup.InitializationProvider"
diff --git a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
index 9c6d102..d3ce67c 100644
--- a/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
+++ b/tests/src/com/android/launcher3/testcomponent/BaseTestingActivity.java
@@ -24,7 +24,9 @@
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
+import android.view.WindowInsets;
import android.widget.Button;
+import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
@@ -81,6 +83,20 @@
mView.addView(button, lp);
}
+ protected void addEditor(String initText, String hint, boolean requestIme) {
+ EditText editText = new EditText(this);
+ editText.setHint(hint);
+ editText.setText(initText);
+
+ LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp.bottomMargin = mMargin;
+ mView.addView(editText, lp);
+ if (requestIme) {
+ editText.requestFocus();
+ mView.getWindowInsetsController().show(WindowInsets.Type.ime());
+ }
+ }
+
@Override
protected void onResume() {
super.onResume();
diff --git a/tests/src/com/android/launcher3/testcomponent/ImeTestActivity.java b/tests/src/com/android/launcher3/testcomponent/ImeTestActivity.java
new file mode 100644
index 0000000..43952d5
--- /dev/null
+++ b/tests/src/com/android/launcher3/testcomponent/ImeTestActivity.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 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.testcomponent;
+
+import android.os.Bundle;
+
+public class ImeTestActivity extends OtherBaseTestingActivity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Requests to focus an editor and show IME for test.
+ addEditor("Focused editor for test", "Focused editor for test", true);
+ }
+}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 2d519d9..70d122b 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -479,6 +479,16 @@
false /* newTask */);
}
+ public static void startImeTestActivity() {
+ final String packageName = getAppPackageName();
+ final Intent intent = getInstrumentation().getContext().getPackageManager().
+ getLaunchIntentForPackage(packageName);
+ intent.setComponent(new ComponentName(packageName,
+ "com.android.launcher3.testcomponent.ImeTestActivity"));
+ startIntent(intent, By.pkg(packageName).text("ImeTestActivity"),
+ false /* newTask */);
+ }
+
private static void startIntent(Intent intent, BySelector selector, boolean newTask) {
intent.addCategory(Intent.CATEGORY_LAUNCHER);
if (newTask) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index eb8d055..15705e7 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -206,21 +206,30 @@
MotionEvent.ACTION_UP, end, gestureScope);
}
+ /**
+ * Quick switching to the app with swiping to right.
+ */
@NonNull
public LaunchedAppState quickSwitchToPreviousApp() {
- boolean toRight = true;
- quickSwitch(toRight);
+ quickSwitch(true /* toRight */);
return new LaunchedAppState(mLauncher);
}
+ /**
+ * Quick switching to the app with swiping to left.
+ */
@NonNull
public LaunchedAppState quickSwitchToPreviousAppSwipeLeft() {
- boolean toRight = false;
- quickSwitch(toRight);
+ quickSwitch(false /* toRight */);
return new LaunchedAppState(mLauncher);
}
- @NonNull
+ /**
+ * Making swipe gesture to quick-switch app tasks.
+ *
+ * @param toRight {@code true} means swiping right, {@code false} means swiping left.
+ * @throws {@link AssertionError} when failing to verify the visible UI in the container.
+ */
private void quickSwitch(boolean toRight) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index a17651b..4b02ecc 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -72,6 +72,16 @@
}
/**
+ * Waits for the taskbar to be visible, or fails.
+ */
+ public void assertTaskbarVisible() {
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "waiting for taskbar to be visible")) {
+ mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
+ }
+ }
+
+ /**
* Returns the Taskbar in a visible state.
*
* The taskbar must already be hidden when calling this method.
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 3986df6..3545c27 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -185,13 +185,14 @@
private final Deque<String> mDiagnosticContext = new LinkedList<>();
private Function<Long, String> mSystemHealthSupplier;
+ private boolean mIgnoreTaskbarVisibility = false;
+
private Consumer<ContainerType> mOnSettledStateAction;
private LogEventChecker mEventChecker;
private boolean mCheckEventsForSuccessfulGestures = false;
private Runnable mOnLauncherCrashed;
-
private static Pattern getTouchEventPattern(String prefix, String action) {
// The pattern includes checks that we don't get a multi-touch events or other surprises.
return Pattern.compile(
@@ -680,6 +681,18 @@
}
}
+ /**
+ * Whether to ignore verifying the task bar visibility during instrumenting.
+ *
+ * @param ignoreTaskbarVisibility {@code true} will ignore the instrumentation implicitly
+ * verifying the task bar visibility with
+ * {@link VisibleContainer#verifyActiveContainer}.
+ * {@code false} otherwise.
+ */
+ public void setIgnoreTaskbarVisibility(boolean ignoreTaskbarVisibility) {
+ mIgnoreTaskbarVisibility = ignoreTaskbarVisibility;
+ }
+
public void setExpectedRotation(int expectedRotation) {
mExpectedRotation = expectedRotation;
}
@@ -798,6 +811,9 @@
waitUntilLauncherObjectGone(WIDGETS_RES_ID);
waitUntilLauncherObjectGone(SPLIT_PLACEHOLDER_RES_ID);
+ if (mIgnoreTaskbarVisibility) {
+ return null;
+ }
if (isTablet() && !isFallbackOverview()) {
waitForLauncherObject(TASKBAR_RES_ID);
} else {