Merge "Fix LauncherProvider newScreenId issue" into sc-v2-dev
diff --git a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
index 492611f..d4eca2f 100644
--- a/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
+++ b/go/quickstep/src/com/android/quickstep/views/GoOverviewActionsView.java
@@ -35,6 +35,7 @@
*/
public class GoOverviewActionsView extends OverviewActionsView<OverlayUICallbacksGo> {
+ @Nullable
private ArrowTipView mArrowTipView;
public GoOverviewActionsView(Context context) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index aa31261..1c0c773 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -15,18 +15,10 @@
*/
package com.android.launcher3.taskbar;
-import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
-import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
-import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION;
-import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
+import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.annotation.ColorInt;
import android.graphics.Rect;
import android.os.RemoteException;
@@ -44,28 +36,17 @@
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.statemanager.StateManager;
-import com.android.launcher3.util.MultiValueAlpha;
-import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
-import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
-import com.android.quickstep.RecentsAnimationController;
-import com.android.quickstep.views.RecentsView;
-import com.android.systemui.shared.recents.model.ThumbnailData;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.Set;
-import java.util.function.Supplier;
import java.util.stream.Stream;
/**
@@ -77,82 +58,15 @@
private final BaseQuickstepLauncher mLauncher;
- private final AnimatedFloat mIconAlignmentForResumedState =
- new AnimatedFloat(this::onIconAlignmentRatioChanged);
- private final AnimatedFloat mIconAlignmentForGestureState =
- new AnimatedFloat(this::onIconAlignmentRatioChanged);
- private final AnimatedFloat mIconAlignmentForLauncherState =
- new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);
-
private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
this::onStashedInAppChanged;
- private final StateManager.StateListener<LauncherState> mStateListener =
- new StateManager.StateListener<LauncherState>() {
- private Animator mAnimator;
-
- @Override
- public void onStateTransitionStart(LauncherState toState) {
- // Stash animation from going to launcher should be already handled in
- // createAnimToLauncher.
- TaskbarStashController controller = mControllers.taskbarStashController;
- long duration = TASKBAR_STASH_DURATION;
- controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
- toState.isTaskbarStashed());
- Animator stashAnimator = controller.applyStateWithoutStart(duration);
- if (stashAnimator != null) {
- if (mAnimator != null) {
- mAnimator.cancel();
- }
- PendingAnimation pendingAnimation = new PendingAnimation(duration);
- pendingAnimation.add(stashAnimator);
- pendingAnimation.setFloat(mIconAlignmentForLauncherState,
- AnimatedFloat.VALUE, toState.isTaskbarStashed() ? 0 : 1,
- FAST_OUT_SLOW_IN);
- pendingAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animator) {
- mTargetStateOverrideForStateTransition = toState;
- // Copy hotseat alpha over to taskbar icons
- mIconAlphaForHome.setValue(mLauncher.getHotseat().getIconsAlpha());
- mLauncher.getHotseat().setIconsAlpha(0);
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- if (toState.isTaskbarStashed()) {
- // Reset hotseat alpha to default
- mLauncher.getHotseat().setIconsAlpha(1);
- }
- mTargetStateOverrideForStateTransition = null;
- mAnimator = null;
- }
- });
- mAnimator = pendingAnimation.buildAnim();
- mAnimator.start();
- }
- }
-
- @Override
- public void onStateTransitionComplete(LauncherState finalState) {
- TaskbarStashController controller = mControllers.taskbarStashController;
- controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
- finalState.isTaskbarStashed());
- controller.applyState();
- }
- };
-
// Initialized in init.
private TaskbarControllers mControllers;
- private AnimatedFloat mTaskbarBackgroundAlpha;
private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
- private AlphaProperty mIconAlphaForHome;
- private boolean mIsAnimatingToLauncherViaResume;
- private boolean mIsAnimatingToLauncherViaGesture;
private TaskbarKeyguardController mKeyguardController;
-
- private LauncherState mTargetStateOverride = null;
- private LauncherState mTargetStateOverrideForStateTransition = null;
+ private final TaskbarLauncherStateController
+ mTaskbarLauncherStateController = new TaskbarLauncherStateController();
private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
new DeviceProfile.OnDeviceProfileChangeListener() {
@@ -171,37 +85,26 @@
protected void init(TaskbarControllers taskbarControllers) {
mControllers = taskbarControllers;
- mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
- .getTaskbarBackgroundAlpha();
+ mTaskbarLauncherStateController.init(mControllers, mLauncher);
mTaskbarOverrideBackgroundAlpha = mControllers.taskbarDragLayerController
.getOverrideBackgroundAlpha();
- MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
- mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
-
mLauncher.setTaskbarUIController(this);
mKeyguardController = taskbarControllers.taskbarKeyguardController;
onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */);
- mIconAlignmentForResumedState.finishAnimation();
- onIconAlignmentRatioChanged();
onStashedInAppChanged(mLauncher.getDeviceProfile());
mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
- mLauncher.getStateManager().addStateListener(mStateListener);
mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
}
@Override
protected void onDestroy() {
onLauncherResumedOrPaused(false);
- mIconAlignmentForResumedState.finishAnimation();
- mIconAlignmentForGestureState.finishAnimation();
- mIconAlignmentForLauncherState.finishAnimation();
+ mTaskbarLauncherStateController.onDestroy();
mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
- mLauncher.getStateManager().removeStateListener(mStateListener);
- mLauncher.getHotseat().setIconsAlpha(1f);
mLauncher.setTaskbarUIController(null);
mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
updateTaskTransitionSpec(true);
@@ -209,11 +112,7 @@
@Override
protected boolean isTaskbarTouchable() {
- return !isAnimatingToLauncher();
- }
-
- private boolean isAnimatingToLauncher() {
- return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
+ return !mTaskbarLauncherStateController.isAnimatingToLauncher();
}
@Override
@@ -240,24 +139,9 @@
}
}
- long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
- if (fromInit) {
- // Since we are creating the starting state, we don't have a state to animate from, so
- // set our state immediately.
- duration = 0;
- }
- ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
- getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
- .setDuration(duration);
-
- anim.addListener(AnimatorListeners.forEndCallback(
- () -> mIsAnimatingToLauncherViaResume = false));
- anim.start();
- mIsAnimatingToLauncherViaResume = isResumed;
-
- TaskbarStashController stashController = mControllers.taskbarStashController;
- stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
- stashController.applyState(duration);
+ mTaskbarLauncherStateController.updateStateForFlag(FLAG_RESUMED, isResumed);
+ mTaskbarLauncherStateController.applyState(
+ fromInit ? 0 : QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
}
/**
@@ -268,77 +152,7 @@
*/
public Animator createAnimToLauncher(@NonNull LauncherState toState,
@NonNull RecentsAnimationCallbacks callbacks, long duration) {
- AnimatorSet animatorSet = new AnimatorSet();
- TaskbarStashController stashController = mControllers.taskbarStashController;
- stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
- toState.isTaskbarStashed());
- if (toState.isTaskbarStashed()) {
- animatorSet.play(stashController.applyStateWithoutStart(duration));
- } else {
- animatorSet.play(mIconAlignmentForGestureState
- .animateToValue(1)
- .setDuration(duration));
- }
- animatorSet.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animator) {
- mTargetStateOverride = null;
- animator.removeListener(this);
- }
-
- @Override
- public void onAnimationStart(Animator animator) {
- mTargetStateOverride = toState;
- mIsAnimatingToLauncherViaGesture = true;
- stashController.updateStateForFlag(FLAG_IN_APP, false);
- stashController.applyState(duration);
- }
- });
-
- TaskBarRecentsAnimationListener listener = new TaskBarRecentsAnimationListener(callbacks);
- callbacks.addListener(listener);
- RecentsView recentsView = mLauncher.getOverviewPanel();
- recentsView.setTaskLaunchListener(() -> {
- listener.endGestureStateOverride(true);
- callbacks.removeListener(listener);
- });
-
- return animatorSet;
- }
-
- private float getCurrentIconAlignmentRatio() {
- return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
- }
-
- private float getCurrentIconAlignmentRatioForLauncherState() {
- return mIconAlignmentForLauncherState.value;
- }
-
- private void onIconAlignmentRatioChangedForStateTransition() {
- onIconAlignmentRatioChanged(
- mTargetStateOverrideForStateTransition != null
- ? mTargetStateOverrideForStateTransition
- : mLauncher.getStateManager().getState(),
- this::getCurrentIconAlignmentRatioForLauncherState);
- }
-
- private void onIconAlignmentRatioChanged() {
- onIconAlignmentRatioChanged(mTargetStateOverride != null ? mTargetStateOverride
- : mLauncher.getStateManager().getState(), this::getCurrentIconAlignmentRatio);
- }
-
- private void onIconAlignmentRatioChanged(LauncherState state,
- Supplier<Float> alignmentSupplier) {
- if (mControllers == null) {
- return;
- }
- float alignment = alignmentSupplier.get();
- mControllers.taskbarViewController.setLauncherIconAlignment(
- alignment, mLauncher.getDeviceProfile());
-
- mTaskbarBackgroundAlpha.updateValue(1 - alignment);
-
- setIconAlpha(state, alignment);
+ return mTaskbarLauncherStateController.createAnimToLauncher(toState, callbacks, duration);
}
/**
@@ -358,20 +172,6 @@
return mControllers.taskbarActivityContext.getDragLayer();
}
- private void setIconAlpha(LauncherState state, float progress) {
- if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
- // If the hotseat icons are visible, then switch taskbar in last frame
- setTaskbarViewVisible(progress < 1);
- } else {
- mIconAlphaForHome.setValue(1 - progress);
- }
- }
-
- private void setTaskbarViewVisible(boolean isVisible) {
- mIconAlphaForHome.setValue(isVisible ? 1 : 0);
- mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
- }
-
@Override
protected void onStashedInAppChanged() {
onStashedInAppChanged(mLauncher.getDeviceProfile());
@@ -451,35 +251,4 @@
mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item,
instanceId);
}
-
- private final class TaskBarRecentsAnimationListener implements RecentsAnimationListener {
- private final RecentsAnimationCallbacks mCallbacks;
-
- TaskBarRecentsAnimationListener(RecentsAnimationCallbacks callbacks) {
- mCallbacks = callbacks;
- }
-
- @Override
- public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
- endGestureStateOverride(true);
- }
-
- @Override
- public void onRecentsAnimationFinished(RecentsAnimationController controller) {
- endGestureStateOverride(!controller.getFinishTargetIsLauncher());
- }
-
- private void endGestureStateOverride(boolean finishedToApp) {
- mCallbacks.removeListener(this);
- mIsAnimatingToLauncherViaGesture = false;
-
- mIconAlignmentForGestureState
- .animateToValue(0)
- .start();
-
- TaskbarStashController controller = mControllers.taskbarStashController;
- controller.updateStateForFlag(FLAG_IN_APP, finishedToApp);
- controller.applyState();
- }
- }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
new file mode 100644
index 0000000..2693bc3
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar;
+
+import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
+import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION;
+import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.statemanager.StateManager;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.quickstep.AnimatedFloat;
+import com.android.quickstep.RecentsAnimationCallbacks;
+import com.android.quickstep.RecentsAnimationController;
+import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+import java.util.HashMap;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * Track LauncherState, RecentsAnimation, resumed state for task bar in one place here and animate
+ * the task bar accordingly.
+ */
+ public class TaskbarLauncherStateController {
+
+ public static final int FLAG_RESUMED = 1 << 0;
+ public static final int FLAG_RECENTS_ANIMATION_RUNNING = 1 << 1;
+ public static final int FLAG_TRANSITION_STATE_START_STASHED = 1 << 2;
+ public static final int FLAG_TRANSITION_STATE_COMMITTED_STASHED = 1 << 3;
+
+ private final AnimatedFloat mIconAlignmentForResumedState =
+ new AnimatedFloat(this::onIconAlignmentRatioChanged);
+ private final AnimatedFloat mIconAlignmentForGestureState =
+ new AnimatedFloat(this::onIconAlignmentRatioChanged);
+ private final AnimatedFloat mIconAlignmentForLauncherState =
+ new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);
+
+ private TaskbarControllers mControllers;
+ private AnimatedFloat mTaskbarBackgroundAlpha;
+ private MultiValueAlpha.AlphaProperty mIconAlphaForHome;
+ private BaseQuickstepLauncher mLauncher;
+
+ private int mPrevState;
+ private int mState;
+
+ private LauncherState mTargetStateOverride = null;
+ private LauncherState mTargetStateOverrideForStateTransition = null;
+
+ private boolean mIsAnimatingToLauncherViaGesture;
+ private boolean mIsAnimatingToLauncherViaResume;
+
+ private final StateManager.StateListener<LauncherState> mStateListener =
+ new StateManager.StateListener<LauncherState>() {
+
+ @Override
+ public void onStateTransitionStart(LauncherState toState) {
+ mTargetStateOverrideForStateTransition = toState;
+ updateStateForFlag(FLAG_TRANSITION_STATE_START_STASHED,
+ toState.isTaskbarStashed());
+ applyState();
+ }
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {
+ updateStateForFlag(FLAG_TRANSITION_STATE_COMMITTED_STASHED,
+ finalState.isTaskbarStashed());
+ applyState();
+ }
+ };
+
+ public void init(TaskbarControllers controllers, BaseQuickstepLauncher launcher) {
+ mControllers = controllers;
+ mLauncher = launcher;
+
+ mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
+ .getTaskbarBackgroundAlpha();
+ MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
+ mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
+ mIconAlphaForHome.setConsumer(
+ (Consumer<Float>) alpha -> mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1));
+
+ mIconAlignmentForResumedState.finishAnimation();
+ onIconAlignmentRatioChanged();
+
+ mLauncher.getStateManager().addStateListener(mStateListener);
+ }
+
+ public void onDestroy() {
+ mIconAlignmentForResumedState.finishAnimation();
+ mIconAlignmentForGestureState.finishAnimation();
+ mIconAlignmentForLauncherState.finishAnimation();
+
+ mLauncher.getHotseat().setIconsAlpha(1f);
+ mLauncher.getStateManager().removeStateListener(mStateListener);
+ }
+
+ public Animator createAnimToLauncher(@NonNull LauncherState toState,
+ @NonNull RecentsAnimationCallbacks callbacks, long duration) {
+ // If going to overview, stash the task bar
+ // If going home, align the icons to hotseat
+ AnimatorSet animatorSet = new AnimatorSet();
+
+ TaskbarStashController stashController = mControllers.taskbarStashController;
+ stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
+ toState.isTaskbarStashed());
+ stashController.updateStateForFlag(FLAG_IN_APP, false);
+
+ updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, true);
+ animatorSet.play(stashController.applyStateWithoutStart(duration));
+ animatorSet.play(applyState(duration, false));
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ mTargetStateOverride = null;
+ animator.removeListener(this);
+ }
+
+ @Override
+ public void onAnimationStart(Animator animator) {
+ mTargetStateOverride = toState;
+ }
+ });
+
+ TaskBarRecentsAnimationListener listener = new TaskBarRecentsAnimationListener(callbacks);
+ callbacks.addListener(listener);
+ RecentsView recentsView = mLauncher.getOverviewPanel();
+ recentsView.setTaskLaunchListener(() -> {
+ listener.endGestureStateOverride(true);
+ callbacks.removeListener(listener);
+ });
+ return animatorSet;
+ }
+
+ public boolean isAnimatingToLauncher() {
+ return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
+ }
+
+ /**
+ * Updates the proper flag to change the state of the task bar.
+ *
+ * Note that this only updates the flag. {@link #applyState()} needs to be called separately.
+ *
+ * @param flag The flag to update.
+ * @param enabled Whether to enable the flag
+ */
+ public void updateStateForFlag(int flag, boolean enabled) {
+ if (enabled) {
+ mState |= flag;
+ } else {
+ mState &= ~flag;
+ }
+ }
+
+ private boolean hasAnyFlag(int flagMask) {
+ return hasAnyFlag(mState, flagMask);
+ }
+
+ private boolean hasAnyFlag(int flags, int flagMask) {
+ return (flags & flagMask) != 0;
+ }
+
+ public void applyState() {
+ applyState(TASKBAR_STASH_DURATION);
+ }
+
+ public void applyState(long duration) {
+ applyState(duration, true);
+ }
+
+ public Animator applyState(boolean start) {
+ return applyState(TASKBAR_STASH_DURATION, start);
+ }
+
+ public Animator applyState(long duration, boolean start) {
+ Animator animator = null;
+ if (mPrevState != mState) {
+ int changedFlags = mPrevState ^ mState;
+ animator = onStateChangeApplied(changedFlags, duration, start);
+ mPrevState = mState;
+ }
+ return animator;
+ }
+
+ private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
+ AnimatorSet animatorSet = new AnimatorSet();
+ if (hasAnyFlag(changedFlags, FLAG_RESUMED)) {
+ boolean isResumed = isResumed();
+ ObjectAnimator anim = mIconAlignmentForResumedState
+ .animateToValue(getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
+ .setDuration(duration);
+
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mIsAnimatingToLauncherViaResume = false;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mIsAnimatingToLauncherViaResume = isResumed;
+
+ TaskbarStashController stashController = mControllers.taskbarStashController;
+ stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
+ stashController.applyState(duration);
+ }
+ });
+ animatorSet.play(anim);
+ }
+
+ if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)) {
+ boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
+ Animator animator = mIconAlignmentForGestureState
+ .animateToValue(isRecentsAnimationRunning ? 1 : 0);
+ if (isRecentsAnimationRunning) {
+ animator.setDuration(duration);
+ }
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mIsAnimatingToLauncherViaGesture = false;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
+ }
+ });
+ animatorSet.play(animator);
+ }
+
+ if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_START_STASHED)) {
+ playStateTransitionAnim(isTransitionStateStartStashed(), animatorSet, duration,
+ false /* committed */);
+ }
+
+ if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_COMMITTED_STASHED)) {
+ playStateTransitionAnim(isTransitionStateCommittedStashed(), animatorSet, duration,
+ true /* committed */);
+ }
+
+ if (start) {
+ animatorSet.start();
+ }
+ return animatorSet;
+ }
+
+ private void playStateTransitionAnim(boolean isTransitionStateStashed,
+ AnimatorSet animatorSet, long duration, boolean committed) {
+ TaskbarStashController controller = mControllers.taskbarStashController;
+ controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
+ isTransitionStateStashed);
+ Animator stashAnimator = controller.applyStateWithoutStart(duration);
+ if (stashAnimator != null) {
+ stashAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (isTransitionStateStashed && committed) {
+ // Reset hotseat alpha to default
+ mLauncher.getHotseat().setIconsAlpha(1);
+ }
+ mTargetStateOverrideForStateTransition = null;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mIconAlphaForHome.setValue(mLauncher.getHotseat().getIconsAlpha());
+ }
+ });
+ animatorSet.play(stashAnimator);
+ animatorSet.play(mIconAlignmentForLauncherState.animateToValue(
+ getCurrentIconAlignmentRatioForLauncherState(),
+ isTransitionStateStashed ? 0 : 1));
+ } else {
+ mTargetStateOverrideForStateTransition = null;
+ }
+ }
+
+ private boolean isResumed() {
+ return (mState & FLAG_RESUMED) != 0;
+ }
+
+ private boolean isRecentsAnimationRunning() {
+ return (mState & FLAG_RECENTS_ANIMATION_RUNNING) != 0;
+ }
+
+ private boolean isTransitionStateStartStashed() {
+ return (mState & FLAG_TRANSITION_STATE_START_STASHED) != 0;
+ }
+
+ private boolean isTransitionStateCommittedStashed() {
+ return (mState & FLAG_TRANSITION_STATE_COMMITTED_STASHED) != 0;
+ }
+
+ private void onIconAlignmentRatioChangedForStateTransition() {
+ onIconAlignmentRatioChanged(
+ mTargetStateOverrideForStateTransition != null
+ ? mTargetStateOverrideForStateTransition
+ : mLauncher.getStateManager().getState(),
+ this::getCurrentIconAlignmentRatioForLauncherState);
+ }
+
+ private void onIconAlignmentRatioChanged() {
+ onIconAlignmentRatioChanged(mTargetStateOverride != null ? mTargetStateOverride
+ : mLauncher.getStateManager().getState(), this::getCurrentIconAlignmentRatio);
+ }
+
+ private void onIconAlignmentRatioChanged(LauncherState state,
+ Supplier<Float> alignmentSupplier) {
+ if (mControllers == null) {
+ return;
+ }
+ float alignment = alignmentSupplier.get();
+ mControllers.taskbarViewController.setLauncherIconAlignment(
+ alignment, mLauncher.getDeviceProfile());
+
+ mTaskbarBackgroundAlpha.updateValue(1 - alignment);
+
+ setIconAlpha(state, alignment);
+ }
+
+ private float getCurrentIconAlignmentRatio() {
+ return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
+ }
+
+ private float getCurrentIconAlignmentRatioForLauncherState() {
+ return mIconAlignmentForLauncherState.value;
+ }
+
+ private void setIconAlpha(LauncherState state, float progress) {
+ if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ // If the hotseat icons are visible, then switch taskbar in last frame
+ setTaskbarViewVisible(progress < 1);
+ } else {
+ mIconAlphaForHome.setValue(1 - progress);
+ }
+ }
+
+ private void setTaskbarViewVisible(boolean isVisible) {
+ mIconAlphaForHome.setValue(isVisible ? 1 : 0);
+ }
+
+ private final class TaskBarRecentsAnimationListener implements
+ RecentsAnimationCallbacks.RecentsAnimationListener {
+ private final RecentsAnimationCallbacks mCallbacks;
+
+ TaskBarRecentsAnimationListener(RecentsAnimationCallbacks callbacks) {
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
+ endGestureStateOverride(true);
+ }
+
+ @Override
+ public void onRecentsAnimationFinished(RecentsAnimationController controller) {
+ endGestureStateOverride(!controller.getFinishTargetIsLauncher());
+ }
+
+ private void endGestureStateOverride(boolean finishedToApp) {
+ mCallbacks.removeListener(this);
+ updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, false);
+ applyState();
+
+ TaskbarStashController controller = mControllers.taskbarStashController;
+ controller.updateStateForFlag(FLAG_IN_APP, finishedToApp);
+ controller.applyState();
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 26d935d..75e8dd1 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -117,11 +117,12 @@
mPendingCommands.clear();
}
+ @Nullable
private TaskView getNextTask(RecentsView view) {
final TaskView runningTaskView = view.getRunningTaskView();
if (runningTaskView == null) {
- return view.getTaskViewCount() > 0 ? view.getTaskViewAt(0) : null;
+ return view.getTaskViewAt(0);
} else {
final TaskView nextTask = view.getNextTaskView();
return nextTask != null ? nextTask : runningTaskView;
@@ -256,8 +257,8 @@
// Ensure that recents view has focus so that it receives the followup key inputs
TaskView taskView = rv.getNextTaskView();
if (taskView == null) {
- if (rv.getTaskViewCount() > 0) {
- taskView = rv.getTaskViewAt(0);
+ taskView = rv.getTaskViewAt(0);
+ if (taskView != null) {
taskView.requestFocus();
} else {
rv.requestFocus();
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index e1afa97..b32c4e5 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -21,8 +21,10 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.RemoteAnimationAdapter;
@@ -78,14 +80,15 @@
*/
public void setSecondTaskId(Task taskView, Consumer<Boolean> callback) {
mSecondTask = taskView;
- launchTasks(mInitialTask, mSecondTask, mStagePosition, callback);
+ launchTasks(mInitialTask, mSecondTask, mStagePosition, callback,
+ false /* freezeTaskList */);
}
/**
* @param stagePosition representing location of task1
*/
public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition,
- Consumer<Boolean> callback) {
+ Consumer<Boolean> callback, boolean freezeTaskList) {
// Assume initial task is for top/left part of screen
final int[] taskIds = stagePosition == STAGE_POSITION_TOP_OR_LEFT
? new int[]{task1.key.id, task2.key.id}
@@ -105,8 +108,13 @@
300, 150,
ActivityThread.currentActivityThread().getApplicationThread());
- mSystemUiProxy.startTasksWithLegacyTransition(taskIds[0], null /* mainOptions */,
- taskIds[1], null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT, adapter);
+ ActivityOptions mainOpts = ActivityOptions.makeBasic();
+ if (freezeTaskList) {
+ mainOpts.setFreezeRecentTasksReordering();
+ }
+ mSystemUiProxy.startTasksWithLegacyTransition(taskIds[0], mainOpts.toBundle(),
+ taskIds[1], null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
+ adapter);
}
}
diff --git a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
index e9d7c3c..d79b318 100644
--- a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
@@ -35,6 +35,7 @@
import android.view.MotionEvent;
import android.view.View;
+import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.AbstractFloatingView;
@@ -58,6 +59,7 @@
private Launcher mLauncher;
private AllAppsEduTouchController mTouchController;
+ @Nullable
private AnimatorSet mAnimation;
private GradientDrawable mCircle;
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 7c8041c..dbdcf19 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -44,6 +44,7 @@
import android.widget.FrameLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import com.android.launcher3.BaseActivity;
@@ -69,6 +70,7 @@
private Task mTask;
private boolean mHasLimit;
private long mAppRemainingTimeMs;
+ @Nullable
private View mBanner;
private ViewOutlineProvider mOldBannerOutlineProvider;
private float mBannerOffsetPercentage;
@@ -234,7 +236,7 @@
task.titleDescription;
}
- private void replaceBanner(View view) {
+ private void replaceBanner(@Nullable View view) {
resetOldBanner();
setBanner(view);
}
@@ -248,7 +250,7 @@
}
}
- private void setBanner(View view) {
+ private void setBanner(@Nullable View view) {
mBanner = view;
if (view != null) {
setupAndAddBanner();
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
index 1548268..c3b166f 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
@@ -27,6 +27,8 @@
import android.view.ViewOutlineProvider;
import android.widget.RemoteViews.RemoteViewOutlineProvider;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.RoundedCornerEnforcement;
@@ -42,7 +44,9 @@
private final DrawableProperties mForegroundProperties = new DrawableProperties();
private final DrawableProperties mBackgroundProperties = new DrawableProperties();
+ @Nullable
private Drawable mOriginalForeground;
+ @Nullable
private Drawable mOriginalBackground;
private float mFinalRadius;
private float mInitialOutlineRadius;
@@ -50,7 +54,7 @@
private boolean mIsUsingFallback;
private View mSourceView;
- FloatingWidgetBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) {
+ FloatingWidgetBackgroundView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -161,8 +165,10 @@
/** Stores and modifies a drawable's properties through an animation. */
private static class DrawableProperties {
+ @Nullable
private Drawable mDrawable;
private float mOriginalRadius;
+ @Nullable
private float[] mOriginalRadii;
private final float[] mTmpRadii = new float[8];
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
index 463ed4b..8a5f42a 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
@@ -57,10 +57,14 @@
private LauncherAppWidgetHostView mAppWidgetView;
private View mAppWidgetBackgroundView;
private RectF mBackgroundPosition;
+ @Nullable
private GhostView mForegroundOverlayView;
+ @Nullable
private Runnable mEndRunnable;
+ @Nullable
private Runnable mFastFinishRunnable;
+ @Nullable
private Runnable mOnTargetChangeRunnable;
private boolean mAppTargetIsTranslucent;
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index ba74b0d..30b55a8 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -39,10 +39,13 @@
*/
public class GroupedTaskView extends TaskView {
+ @Nullable
private Task mSecondaryTask;
private TaskThumbnailView mSnapshotView2;
private IconView mIconView2;
+ @Nullable
private CancellableTask<ThumbnailData> mThumbnailLoadRequest2;
+ @Nullable
private CancellableTask mIconLoadRequest2;
private final float[] mIcon2CenterCoords = new float[2];
private TransformingTouchDelegate mIcon2TouchDelegate;
@@ -153,21 +156,23 @@
}
}
+ @Nullable
@Override
public RunnableList launchTaskAnimated() {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
+ STAGE_POSITION_TOP_OR_LEFT, null /*callback*/,
+ false /* freezeTaskList */);
return null;
}
@Override
public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
- STAGE_POSITION_TOP_OR_LEFT, callback);
+ STAGE_POSITION_TOP_OR_LEFT, callback, freezeTaskList);
}
@Override
- void refreshThumbnails(HashMap<Integer, ThumbnailData> thumbnailDatas) {
+ void refreshThumbnails(@Nullable HashMap<Integer, ThumbnailData> thumbnailDatas) {
super.refreshThumbnails(thumbnailDatas);
if (mSecondaryTask != null && thumbnailDatas != null) {
final ThumbnailData thumbnailData = thumbnailDatas.get(mSecondaryTask.key.id);
diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java
index 813e653..ccb1a99 100644
--- a/quickstep/src/com/android/quickstep/views/IconView.java
+++ b/quickstep/src/com/android/quickstep/views/IconView.java
@@ -23,6 +23,8 @@
import android.view.Gravity;
import android.view.View;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Utilities;
/**
@@ -31,6 +33,7 @@
*/
public class IconView extends View {
+ @Nullable
private Drawable mDrawable;
private int mDrawableWidth, mDrawableHeight;
@@ -46,7 +49,10 @@
super(context, attrs, defStyleAttr);
}
- public void setDrawable(Drawable d) {
+ /**
+ * Sets a {@link Drawable} to be displayed.
+ */
+ public void setDrawable(@Nullable Drawable d) {
if (mDrawable != null) {
mDrawable.setCallback(null);
}
@@ -76,6 +82,7 @@
mDrawable.setBounds(drawableRect);
}
+ @Nullable
public Drawable getDrawable() {
return mDrawable;
}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 5c0b50c..f3b6a63 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -90,8 +90,10 @@
@ActionsDisabledFlags
protected int mDisabledFlags;
+ @Nullable
protected T mCallbacks;
+ @Nullable
protected DeviceProfile mDp;
public OverviewActionsView(Context context) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 223ce1c..92f1a67 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -383,7 +383,9 @@
protected final RecentsOrientedState mOrientationState;
protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
+ @Nullable
protected RecentsAnimationController mRecentsAnimationController;
+ @Nullable
protected SurfaceTransactionApplier mSyncTransactionApplier;
protected int mTaskWidth;
protected int mTaskHeight;
@@ -394,12 +396,15 @@
// mTaskGridVerticalDiff and mTopBottomRowHeightDiff summed together provides the top
// position for bottom row of grid tasks.
+ @Nullable
protected RemoteTargetHandle[] mRemoteTargetHandles;
protected final Rect mLastComputedTaskSize = new Rect();
protected final Rect mLastComputedGridSize = new Rect();
protected final Rect mLastComputedGridTaskSize = new Rect();
// How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
+ @Nullable
protected Float mLastComputedTaskStartPushOutDistance = null;
+ @Nullable
protected Float mLastComputedTaskEndPushOutDistance = null;
protected boolean mEnableDrawingLiveTile = false;
protected final Rect mTempRect = new Rect();
@@ -454,11 +459,13 @@
private final IntSet mTopRowIdSet = new IntSet();
// The GestureEndTarget that is still in progress.
+ @Nullable
protected GestureState.GestureEndTarget mCurrentGestureEndTarget;
// TODO(b/187528071): Remove these and replace with a real scrim.
private float mColorTint;
private final int mTintingColor;
+ @Nullable
private ObjectAnimator mTintingAnimator;
private int mOverScrollShift = 0;
@@ -542,6 +549,7 @@
private int mTaskViewIdCount;
private final int[] INVALID_TASK_IDS = new int[]{-1, -1};
protected boolean mRunningTaskTileHidden;
+ @Nullable
private Task[] mTmpRunningTasks;
protected int mFocusedTaskViewId = -1;
@@ -556,7 +564,9 @@
private int mDownX;
private int mDownY;
+ @Nullable
private PendingAnimation mPendingAnimation;
+ @Nullable
private LayoutTransition mLayoutTransition;
@ViewDebug.ExportedProperty(category = "launcher")
@@ -581,7 +591,9 @@
private final Point mLastMeasureSize = new Point();
private final int mEmptyMessagePadding;
private boolean mShowEmptyMessage;
+ @Nullable
private OnEmptyMessageUpdatedListener mOnEmptyMessageUpdatedListener;
+ @Nullable
private Layout mEmptyTextLayout;
/**
@@ -596,8 +608,11 @@
* ensure this View doesn't go back into the {@link #mTaskViewPool},
* see {@link #onViewRemoved(View)}
*/
+ @Nullable
private TaskView mSplitHiddenTaskView;
+ @Nullable
private TaskView mSecondSplitHiddenTaskView;
+ @Nullable
private StagedSplitBounds mSplitBoundsConfig;
private final Toast mSplitToast = Toast.makeText(getContext(),
R.string.toast_split_select_app, Toast.LENGTH_SHORT);
@@ -613,12 +628,15 @@
* removed from recentsView
*/
private int mSplitHiddenTaskViewIndex;
+ @Nullable
private FloatingTaskView mFirstFloatingTaskView;
+ @Nullable
private FloatingTaskView mSecondFloatingTaskView;
/**
* The task to be removed and immediately re-added. Should not be added to task pool.
*/
+ @Nullable
private TaskView mMovingTaskView;
private OverviewActionsView mActionsView;
@@ -638,10 +656,12 @@
}
};
+ @Nullable
private RunnableList mSideTaskLaunchCallback;
+ @Nullable
private TaskLaunchListener mTaskLaunchListener;
- public RecentsView(Context context, AttributeSet attrs, int defStyleAttr,
+ public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
BaseActivityInterface sizeStrategy) {
super(context, attrs, defStyleAttr);
setEnableFreeScroll(true);
@@ -782,6 +802,7 @@
}
@Override
+ @Nullable
public Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData) {
if (mHandleTaskStackChanges) {
TaskView taskView = getTaskViewByTaskId(taskId);
@@ -1017,6 +1038,7 @@
}
}
+ @Nullable
private TaskView getLastGridTaskView() {
return getLastGridTaskView(getTopRowIdArray(), getBottomRowIdArray());
}
@@ -1070,6 +1092,10 @@
return getScrollForPage(taskIndex) == getPagedOrientationHandler().getPrimaryScroll(this);
}
+ /**
+ * Returns a {@link TaskView} that has taskId matching {@code taskId} or null if no match.
+ */
+ @Nullable
public TaskView getTaskViewByTaskId(int taskId) {
if (taskId == -1) {
return null;
@@ -1920,6 +1946,7 @@
return getTaskViewFromTaskViewId(mFocusedTaskViewId);
}
+ @Nullable
private TaskView getTaskViewFromTaskViewId(int taskViewId) {
if (taskViewId == -1) {
return null;
@@ -4371,12 +4398,15 @@
}
}
- public void finishRecentsAnimation(boolean toRecents, Runnable onFinishComplete) {
+ /**
+ * Finish recents animation.
+ */
+ public void finishRecentsAnimation(boolean toRecents, @Nullable Runnable onFinishComplete) {
finishRecentsAnimation(toRecents, true /* shouldPip */, onFinishComplete);
}
public void finishRecentsAnimation(boolean toRecents, boolean shouldPip,
- Runnable onFinishComplete) {
+ @Nullable Runnable onFinishComplete) {
// TODO(b/197232424#comment#10) Move this back into onRecentsAnimationComplete(). Maybe?
cleanupRemoteTargets();
if (!toRecents && ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -4939,10 +4969,13 @@
private static class PinnedStackAnimationListener<T extends BaseActivity> extends
IPipAnimationListener.Stub {
+ @Nullable
private T mActivity;
+ @Nullable
private RecentsView mRecentsView;
- public void setActivityAndRecentsView(T activity, RecentsView recentsView) {
+ public void setActivityAndRecentsView(@Nullable T activity,
+ @Nullable RecentsView recentsView) {
mActivity = activity;
mRecentsView = recentsView;
}
diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
index 845e13e..04a5761 100644
--- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
@@ -40,6 +40,7 @@
}
};
+ @Nullable
private IconView mIconView;
public SplitPlaceholderView(Context context, AttributeSet attrs) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index d55b89c..853a023 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -39,6 +39,8 @@
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -67,6 +69,7 @@
private BaseDraggingActivity mActivity;
private TextView mTaskName;
+ @Nullable
private AnimatorSet mOpenCloseAnimator;
private TaskView mTaskView;
private TaskIdAttributeContainer mTaskContainer;
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index d498428..f8368ae 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -78,6 +78,7 @@
};
private final BaseActivity mActivity;
+ @Nullable
private TaskOverlay mOverlay;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -90,8 +91,11 @@
private final PreviewPositionHelper mPreviewPositionHelper = new PreviewPositionHelper();
private TaskView.FullscreenDrawParams mFullscreenParams;
+ @Nullable
private Task mTask;
+ @Nullable
private ThumbnailData mThumbnailData;
+ @Nullable
protected BitmapShader mBitmapShader;
/** How much this thumbnail is dimmed, 0 not dimmed at all, 1 totally dimmed. */
@@ -141,7 +145,8 @@
* upon swipe up so that a usable screenshot is accessible immediately when
* recents animation needs to be finished / cancelled.
*/
- public void setThumbnail(Task task, ThumbnailData thumbnailData, boolean refreshNow) {
+ public void setThumbnail(@Nullable Task task, @Nullable ThumbnailData thumbnailData,
+ boolean refreshNow) {
mTask = task;
mThumbnailData =
(thumbnailData != null && thumbnailData.thumbnail != null) ? thumbnailData : null;
@@ -151,7 +156,7 @@
}
/** See {@link #setThumbnail(Task, ThumbnailData, boolean)} */
- public void setThumbnail(Task task, ThumbnailData thumbnailData) {
+ public void setThumbnail(@Nullable Task task, @Nullable ThumbnailData thumbnailData) {
setThumbnail(task, thumbnailData, true /* refreshNow */);
}
@@ -366,6 +371,10 @@
return Utilities.makeColorTintingColorFilter(mDimColor, dimAmount);
}
+ /**
+ * Returns current thumbnail or null if none is set.
+ */
+ @Nullable
public Bitmap getThumbnail() {
if (mThumbnailData == null) {
return null;
@@ -450,15 +459,36 @@
float availableHeight = surfaceHeight
- (thumbnailClipHint.top + thumbnailClipHint.bottom);
- if (isRotated) {
- float canvasAspect = canvasWidth / (float) canvasHeight;
- float availableAspect = availableHeight / availableWidth;
+ float canvasAspect = canvasWidth / (float) canvasHeight;
+ float availableAspect = isRotated
+ ? availableHeight / availableWidth
+ : availableWidth / availableHeight;
+ boolean isAspectLargelyDifferent = Utilities.isRelativePercentDifferenceGreaterThan(
+ canvasAspect, availableAspect, 0.1f);
+ if (isRotated && isAspectLargelyDifferent) {
// Do not rotate thumbnail if it would not improve fit
- if (Utilities.isRelativePercentDifferenceGreaterThan(canvasAspect,
- availableAspect, 0.1f)) {
- isRotated = false;
- isOrientationDifferent = false;
+ isRotated = false;
+ isOrientationDifferent = false;
+ }
+
+ if (isAspectLargelyDifferent) {
+ // Crop letterbox insets if insets isn't already clipped
+ if (!TaskView.clipLeft(dp)) {
+ thumbnailClipHint.left = thumbnailData.letterboxInsets.left;
}
+ if (!TaskView.clipRight(dp)) {
+ thumbnailClipHint.right = thumbnailData.letterboxInsets.right;
+ }
+ if (!TaskView.clipTop(dp)) {
+ thumbnailClipHint.top = thumbnailData.letterboxInsets.top;
+ }
+ if (!TaskView.clipBottom(dp)) {
+ thumbnailClipHint.bottom = thumbnailData.letterboxInsets.bottom;
+ }
+ availableWidth = surfaceWidth
+ - (thumbnailClipHint.left + thumbnailClipHint.right);
+ availableHeight = surfaceHeight
+ - (thumbnailClipHint.top + thumbnailClipHint.bottom);
}
final float targetW, targetH;
@@ -469,30 +499,25 @@
targetW = canvasWidth;
targetH = canvasHeight;
}
- float canvasAspect = targetW / targetH;
+ float targetAspect = targetW / targetH;
// Update the clipHint such that
// > the final clipped position has same aspect ratio as requested by canvas
- // > the clipped region is within the task insets if possible
- // > the clipped region is not scaled up when drawing. If that is not possible
- // while staying within the taskInsets, move outside the insets.
+ // > 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;
- if (croppedWidth < targetW) {
- croppedWidth = Math.min(targetW, surfaceWidth);
- }
-
- float croppedHeight = croppedWidth / canvasAspect;
+ float croppedHeight = croppedWidth / targetAspect;
if (croppedHeight > availableHeight) {
croppedHeight = availableHeight;
if (croppedHeight < targetH) {
croppedHeight = Math.min(targetH, surfaceHeight);
}
- croppedWidth = croppedHeight * canvasAspect;
+ croppedWidth = croppedHeight * targetAspect;
// One last check in case the task aspect radio messed up something
if (croppedWidth > surfaceWidth) {
croppedWidth = surfaceWidth;
- croppedHeight = croppedWidth / canvasAspect;
+ croppedHeight = croppedWidth / targetAspect;
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 9f961c9..3da7893 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -360,6 +360,7 @@
private final TaskOutlineProvider mOutlineProvider;
+ @Nullable
protected Task mTask;
protected TaskThumbnailView mSnapshotView;
protected IconView mIconView;
@@ -394,6 +395,7 @@
private float mSplitSelectTranslationX;
private float mSplitSelectScrollOffsetPrimary;
+ @Nullable
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
private float mFocusTransitionProgress = 1;
@@ -411,7 +413,9 @@
private boolean mShowScreenshot;
// The current background requests to load the task thumbnail and icon
+ @Nullable
private CancellableTask mThumbnailLoadRequest;
+ @Nullable
private CancellableTask mIconLoadRequest;
private boolean mEndQuickswitchCuj;
@@ -544,6 +548,7 @@
return mTaskIdAttributeContainer;
}
+ @Nullable
public Task getTask() {
return mTask;
}
@@ -686,6 +691,7 @@
* Starts the task associated with this view and animates the startup.
* @return CompletionStage to indicate the animation completion or null if the launch failed.
*/
+ @Nullable
public RunnableList launchTaskAnimated() {
if (mTask != null) {
TestLogging.recordEvent(
@@ -843,7 +849,7 @@
}
}
- protected void setIcon(IconView iconView, Drawable icon) {
+ protected void setIcon(IconView iconView, @Nullable Drawable icon) {
if (icon != null) {
iconView.setDrawable(icon);
iconView.setOnClickListener(v -> {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 523ac72..cefadf7 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1721,6 +1721,10 @@
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ if (mScroller.isFinished()) {
+ // This was not caused by the scroller, skip it.
+ return;
+ }
int newDestinationPage = getDestinationPage();
if (newDestinationPage >= 0 && newDestinationPage != mCurrentScrollOverPage) {
mCurrentScrollOverPage = newDestinationPage;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index e24ea66..e253505 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -157,15 +157,6 @@
"ENABLE_DATABASE_RESTORE", false,
"Enable database restore when new restore session is created");
- public static final BooleanFlag ENABLE_SMARTSPACE_UNIVERSAL = getDebugFlag(
- "ENABLE_SMARTSPACE_UNIVERSAL", false,
- "Replace Smartspace with a version rendered by System UI.");
-
- public static final BooleanFlag ENABLE_SMARTSPACE_ENHANCED = getDebugFlag(
- "ENABLE_SMARTSPACE_ENHANCED", true,
- "Replace Smartspace with the enhanced version. "
- + "Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
-
public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(
"ENABLE_SMARTSPACE_DISMISS", true,
"Adds a menu option to dismiss the current Enhanced Smartspace card.");
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
index bd39391..326141d 100644
--- a/src/com/android/launcher3/util/MultiValueAlpha.java
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -24,6 +24,7 @@
import com.android.launcher3.anim.AlphaUpdateListener;
import java.util.Arrays;
+import java.util.function.Consumer;
/**
* Utility class to handle separating a single value as a factor of multiple values
@@ -85,6 +86,8 @@
// Factor of all other alpha channels, only valid if mMyMask is present in mValidMask.
private float mOthers = 1;
+ private Consumer<Float> mConsumer;
+
AlphaProperty(int myMask) {
mMyMask = myMask;
}
@@ -109,16 +112,24 @@
mValidMask = mMyMask;
mValue = value;
- mView.setAlpha(mOthers * mValue);
+ final float alpha = mOthers * mValue;
+ mView.setAlpha(alpha);
if (mUpdateVisibility) {
AlphaUpdateListener.updateVisibility(mView);
}
+ if (mConsumer != null) {
+ mConsumer.accept(mValue);
+ }
}
public float getValue() {
return mValue;
}
+ public void setConsumer(Consumer<Float> consumer) {
+ mConsumer = consumer;
+ }
+
@Override
public String toString() {
return Float.toString(mValue);
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index a9bcd67..c90d283 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -107,14 +107,6 @@
mLauncher.pressHome();
}
- @Ignore
- public void testOpenHomeSettingsFromWorkspace() {
- mDevice.pressMenu();
- mDevice.waitForIdle();
- mLauncher.getOptionsPopupMenu().getMenuItem("Home settings")
- .launch(mDevice.getLauncherPackageName());
- }
-
@Test
public void testPressHomeOnAllAppsContextMenu() throws Exception {
final AllApps allApps = mLauncher.getWorkspace().switchToAllApps();
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index f3e3ec5..2fbe460 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1025,20 +1025,6 @@
}
}
- /**
- * Gets the Options Popup Menu object if the current state is showing the popup menu. Fails if
- * the launcher is not in that state.
- *
- * @return Options Popup Menu object.
- */
- @NonNull
- public OptionsPopupMenu getOptionsPopupMenu() {
- try (LauncherInstrumentation.Closable c = addContextLayer(
- "want to get context menu object")) {
- return new OptionsPopupMenu(this);
- }
- }
-
void waitUntilLauncherObjectGone(String resId) {
waitUntilGoneBySelector(getLauncherObjectSelector(resId));
}
diff --git a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenu.java b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenu.java
deleted file mode 100644
index 787dc70..0000000
--- a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenu.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2020 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.tapl;
-
-import androidx.annotation.NonNull;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiObject2;
-
-public class OptionsPopupMenu {
-
- private final LauncherInstrumentation mLauncher;
- private final UiObject2 mDeepShortcutsContainer;
-
- OptionsPopupMenu(LauncherInstrumentation launcher) {
- mLauncher = launcher;
- mDeepShortcutsContainer = launcher.waitForLauncherObject("popup_container");
- }
-
- /**
- * Returns a menu item with a given label. Fails if it doesn't exist.
- */
- @NonNull
- public OptionsPopupMenuItem getMenuItem(@NonNull final String label) {
- final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
- By.text(label));
- return new OptionsPopupMenuItem(mLauncher, menuItem);
- }
-}