Merge "Show IME suggestions while tapping on Folder EditText" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 95198b8..9afa862 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -20,15 +20,14 @@
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
@@ -47,9 +46,9 @@
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.util.AppWindowAnimationHelper;
import com.android.quickstep.views.RecentsView;
@@ -210,17 +209,20 @@
.setValues(values)
.build(mLauncher);
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
- builder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
+
+ config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
- builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
- builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
}
+
+
LauncherStateManager stateManager = mLauncher.getStateManager();
return stateManager.createAtomicAnimation(
- stateManager.getCurrentStableState(), OVERVIEW, builder,
- ANIM_ALL_COMPONENTS, ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW);
+ stateManager.getCurrentStableState(), OVERVIEW, config);
}
default:
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 65aaf22..549187f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -20,7 +20,6 @@
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
-import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
@@ -29,10 +28,10 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -61,25 +60,22 @@
}
@Override
- void setStateWithAnimationInternal(@NonNull final LauncherState toState,
- @NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
- super.setStateWithAnimationInternal(toState, builder, config);
+ void setStateWithAnimationInternal(@NonNull LauncherState toState,
+ @NonNull StateAnimationConfig config, @NonNull PendingAnimation builder) {
+ super.setStateWithAnimationInternal(toState, config, builder);
- ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1).setDuration(config.duration);
if (toState.overviewUi) {
// While animating into recents, update the visible task data as needed
- updateAnim.addUpdateListener(valueAnimator -> mRecentsView.loadVisibleTaskData());
+ builder.addOnFrameCallback(mRecentsView::loadVisibleTaskData);
mRecentsView.updateEmptyMessage();
} else {
- updateAnim.addListener(
+ builder.getAnim().addListener(
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
}
- builder.play(updateAnim);
- PropertySetter propertySetter = config.getPropertySetter(builder);
- setAlphas(propertySetter, toState.getVisibleElements(mLauncher));
- float fullscreenProgress = toState.getOverviewFullscreenProgress();
- propertySetter.setFloat(mRecentsView, FULLSCREEN_PROGRESS, fullscreenProgress, LINEAR);
+ setAlphas(builder, toState.getVisibleElements(mLauncher));
+ builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
+ toState.getOverviewFullscreenProgress(), LINEAR);
}
private void setAlphas(PropertySetter propertySetter, int visibleElements) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
index 427206a..8087611 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
@@ -14,17 +14,18 @@
* limitations under the License.
*/
package com.android.launcher3.uioverrides.states;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCRIM_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
+
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.states.StateAnimationConfig;
public class OverviewPeekState extends OverviewState {
public OverviewPeekState(int id) {
@@ -41,11 +42,11 @@
@Override
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
- AnimatorSetBuilder builder) {
+ StateAnimationConfig config) {
if (this == OVERVIEW_PEEK && fromState == NORMAL) {
- builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
- builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
- builder.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
+ config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
+ config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
}
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index bfbb630..6a34917 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -18,13 +18,6 @@
import static android.view.View.VISIBLE;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -32,6 +25,13 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
@@ -48,8 +48,8 @@
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
@@ -225,14 +225,14 @@
@Override
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
- AnimatorSetBuilder builder) {
+ StateAnimationConfig config) {
if ((fromState == NORMAL || fromState == HINT_STATE) && this == OVERVIEW) {
if (SysUINavigationMode.getMode(launcher) == NO_BUTTON) {
- builder.setInterpolator(ANIM_WORKSPACE_SCALE,
+ config.setInterpolator(ANIM_WORKSPACE_SCALE,
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
- builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
+ config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
} else {
- builder.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
// Scale up the recents, if it is not coming from the side
RecentsView overview = launcher.getOverviewPanel();
@@ -240,15 +240,15 @@
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
}
}
- builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
- builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
&& removeShelfFromOverview(launcher)
? OVERSHOOT_1_2
: OVERSHOOT_1_7;
- builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
- builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
- builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, translationInterpolator);
+ config.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index b347013..6fc03b1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -21,16 +21,16 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
-import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_PEEK;
-import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
+import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -44,10 +44,10 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppTransitionManagerImpl;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationFlags;
import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SystemUiProxy;
@@ -105,8 +105,12 @@
LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK;
LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL;
long peekDuration = isPaused ? PEEK_IN_ANIM_DURATION : PEEK_OUT_ANIM_DURATION;
- mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(fromState, toState,
- new AnimatorSetBuilder(), PLAY_ATOMIC_OVERVIEW_PEEK, peekDuration);
+
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.duration = peekDuration;
+ config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
+ mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
+ fromState, toState, config);
mPeekAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -116,8 +120,8 @@
mPeekAnim.start();
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
- mLauncher.getDragLayer().getScrim().animateToSysuiMultiplier(isPaused ? 0 : 1,
- peekDuration, 0);
+ mLauncher.getDragLayer().getScrim().createSysuiMultiplierAnim(isPaused ? 0 : 1)
+ .setDuration(peekDuration).start();
}
/**
@@ -130,10 +134,10 @@
}
@Override
- protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
- LauncherState toState) {
+ protected StateAnimationConfig getConfigForStates(
+ LauncherState fromState, LauncherState toState) {
if (fromState == NORMAL && toState == ALL_APPS) {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ StateAnimationConfig builder = new StateAnimationConfig();
// Fade in prediction icons quickly, then rest of all apps after reaching overview.
float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
- OVERVIEW.getVerticalProgress(mLauncher);
@@ -152,7 +156,7 @@
builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
return builder;
} else if (fromState == ALL_APPS && toState == NORMAL) {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ StateAnimationConfig builder = new StateAnimationConfig();
// Keep all apps/predictions opaque until the very end of the transition.
float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
@@ -165,7 +169,7 @@
1));
return builder;
}
- return super.getAnimatorSetBuilderForStates(fromState, toState);
+ return super.getConfigForStates(fromState, toState);
}
@Override
@@ -211,9 +215,11 @@
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (mCancelled) {
- mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(mFromState,
- mToState, new AnimatorSetBuilder(), PLAY_ATOMIC_OVERVIEW_PEEK,
- PEEK_OUT_ANIM_DURATION);
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
+ config.duration = PEEK_OUT_ANIM_DURATION;
+ mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
+ mFromState, mToState, config);
mPeekAnim.start();
}
mAtomicAnim = null;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index a0ca886..77118d5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -15,8 +15,7 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
-import static android.view.View.TRANSLATION_X;
-
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -26,9 +25,6 @@
import static com.android.launcher3.touch.AbstractStateChangeTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -36,16 +32,16 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -132,46 +128,37 @@
private void initCurrentAnimation() {
long accuracy = (long) (getShiftRange() * 2);
- final AnimatorSet anim = new AnimatorSet();
+ final PendingAnimation builder = new PendingAnimation(accuracy);
if (mStartState == OVERVIEW) {
RecentsView recentsView = mLauncher.getOverviewPanel();
float pullbackDist = mPullbackDistance;
if (!recentsView.isRtl()) {
pullbackDist = -pullbackDist;
}
- ObjectAnimator pullback = ObjectAnimator.ofFloat(recentsView, TRANSLATION_X,
- pullbackDist);
- pullback.setInterpolator(PULLBACK_INTERPOLATOR);
+
+ builder.setFloat(recentsView, VIEW_TRANSLATE_X, pullbackDist, PULLBACK_INTERPOLATOR);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
- pullback.addUpdateListener(
- valueAnimator -> recentsView.redrawLiveTile(false /* mightNeedToRefill */));
+ builder.addOnFrameCallback(
+ () -> recentsView.redrawLiveTile(false /* mightNeedToRefill */));
}
- anim.play(pullback);
} else if (mStartState == ALL_APPS) {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
- Animator allAppsProgress = ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS,
- -mPullbackDistance / allAppsController.getShiftRange());
- allAppsProgress.setInterpolator(PULLBACK_INTERPOLATOR);
- builder.play(allAppsProgress);
+ builder.setFloat(allAppsController, ALL_APPS_PROGRESS,
+ -mPullbackDistance / allAppsController.getShiftRange(), PULLBACK_INTERPOLATOR);
+
// Slightly fade out all apps content to further distinguish from scrolling.
- builder.setInterpolator(AnimatorSetBuilder.ANIM_ALL_APPS_FADE, Interpolators
- .mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f));
- AnimationConfig config = new AnimationConfig();
+ StateAnimationConfig config = new StateAnimationConfig();
config.duration = accuracy;
- allAppsController.setAlphas(mEndState.getVisibleElements(mLauncher), config, builder);
- anim.play(builder.build());
+ config.setInterpolator(StateAnimationConfig.ANIM_ALL_APPS_FADE, Interpolators
+ .mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f));
+
+ allAppsController.setAlphas(mEndState, config, builder);
}
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
if (topView != null) {
- Animator hintCloseAnim = topView.createHintCloseAnim(mPullbackDistance);
- if (hintCloseAnim != null) {
- hintCloseAnim.setInterpolator(PULLBACK_INTERPOLATOR);
- anim.play(hintCloseAnim);
- }
+ topView.addHintCloseAnim(mPullbackDistance, PULLBACK_INTERPOLATOR, builder);
}
- anim.setDuration(accuracy);
- mCurrentAnimation = AnimatorPlaybackController.wrap(anim, accuracy)
+ mCurrentAnimation = builder.createPlaybackController()
.setOnCancelRunnable(this::clearState);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 7cebabe..064133c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -19,9 +19,9 @@
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import android.animation.AnimatorSet;
@@ -34,7 +34,7 @@
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
@@ -171,11 +171,11 @@
// StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
stateManager.cancelAnimation();
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- long duration = OVERVIEW.getTransitionDuration(mLauncher);
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.duration = OVERVIEW.getTransitionDuration(mLauncher);
+ config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
AnimatorSet anim = stateManager.createAtomicAnimation(
- stateManager.getState(), NORMAL, builder,
- PLAY_ATOMIC_OVERVIEW_PEEK, duration);
+ stateManager.getState(), NORMAL, config);
anim.addListener(AnimationSuccessListener.forRunnable(
() -> onSwipeInteractionCompleted(NORMAL, Touch.SWIPE)));
anim.start();
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 81a6d9b..c92a872 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -21,18 +21,18 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
-import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
+import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
@@ -55,15 +55,13 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
-import com.android.launcher3.LauncherStateManager.AnimationFlags;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.OverviewScrim;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.BaseSwipeDetector;
import com.android.launcher3.touch.BothAxesSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -192,11 +190,9 @@
ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
if (shelfState == PEEK) {
// Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
- allAppsController.setAlphas(NORMAL.getVisibleElements(mLauncher),
- new AnimationConfig(), builder);
- builder.build().setDuration(0).start();
+ allAppsController.setAlphas(
+ NORMAL, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
// Hotseat was hidden, but we need it visible when peeking.
@@ -209,12 +205,12 @@
private void setupAnimators() {
// Animate the non-overview components (e.g. workspace, shelf) out of the way.
- AnimatorSetBuilder nonOverviewBuilder = new AnimatorSetBuilder();
+ StateAnimationConfig nonOverviewBuilder = new StateAnimationConfig();
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_FADE, FADE_OUT_INTERPOLATOR);
nonOverviewBuilder.setInterpolator(ANIM_ALL_APPS_FADE, FADE_OUT_INTERPOLATOR);
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, TRANSLATE_OUT_INTERPOLATOR);
nonOverviewBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, TRANSLATE_OUT_INTERPOLATOR);
- updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder, ANIM_ALL_COMPONENTS);
+ updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder);
mNonOverviewAnim.dispatchOnStart();
if (mRecentsView.getTaskViewCount() == 0) {
@@ -230,11 +226,12 @@
}
/** Create state animation to control non-overview components. */
- private void updateNonOverviewAnim(LauncherState toState, AnimatorSetBuilder builder,
- @AnimationFlags int animComponents) {
- long accuracy = (long) (Math.max(mXRange, mYRange) * 2);
- mNonOverviewAnim = mLauncher.getStateManager().createAnimationToNewWorkspace(toState,
- builder, accuracy, this::clearState, animComponents | SKIP_OVERVIEW);
+ private void updateNonOverviewAnim(LauncherState toState, StateAnimationConfig config) {
+ config.duration = (long) (Math.max(mXRange, mYRange) * 2);
+ config.animFlags = config.animFlags | SKIP_OVERVIEW;
+ mNonOverviewAnim = mLauncher.getStateManager()
+ .createAnimationToNewWorkspace(toState, config)
+ .setOnCancelRunnable(this::clearState);
}
private void setupOverviewAnimators() {
@@ -419,8 +416,10 @@
if (flingUpToNormal && !mIsHomeScreenVisible) {
// We are flinging to home while workspace is invisible, run the same staggered
// animation as from an app.
+ StateAnimationConfig config = new StateAnimationConfig();
// Update mNonOverviewAnim to do nothing so it doesn't interfere.
- updateNonOverviewAnim(targetState, new AnimatorSetBuilder(), 0 /* animComponents */);
+ config.animFlags = 0;
+ updateNonOverviewAnim(targetState, config);
nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
new StaggeredWorkspaceAnim(mLauncher, velocity.y, false /* animateOverviewScrim */)
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index 8de1b3a..9e53959 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -17,18 +17,17 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -41,7 +40,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -108,30 +107,30 @@
@Override
protected float initCurrentAnimation(int animComponents) {
- AnimatorSetBuilder animatorSetBuilder = new AnimatorSetBuilder();
- setupInterpolators(animatorSetBuilder);
- long accuracy = (long) (getShiftRange() * 2);
- mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(mToState,
- animatorSetBuilder, accuracy, this::clearState, ANIM_ALL_COMPONENTS);
- mCurrentAnimation.getAnimationPlayer().addUpdateListener(valueAnimator -> {
- updateFullscreenProgress((Float) valueAnimator.getAnimatedValue());
- });
+ StateAnimationConfig config = new StateAnimationConfig();
+ setupInterpolators(config);
+ config.duration = (long) (getShiftRange() * 2);
+ mCurrentAnimation = mLauncher.getStateManager()
+ .createAnimationToNewWorkspace(mToState, config)
+ .setOnCancelRunnable(this::clearState);
+ mCurrentAnimation.getAnimationPlayer().addUpdateListener(valueAnimator ->
+ updateFullscreenProgress((Float) valueAnimator.getAnimatedValue()));
return 1 / getShiftRange();
}
- private void setupInterpolators(AnimatorSetBuilder animatorSetBuilder) {
- animatorSetBuilder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
- animatorSetBuilder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
+ private void setupInterpolators(StateAnimationConfig stateAnimationConfig) {
+ stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
if (SysUINavigationMode.getMode(mLauncher) == Mode.NO_BUTTON) {
// Overview lives to the left of workspace, so translate down later than over
- animatorSetBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL_2);
- animatorSetBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCEL_2);
- animatorSetBuilder.setInterpolator(ANIM_OVERVIEW_SCALE, ACCEL_2);
- animatorSetBuilder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCEL_2);
- animatorSetBuilder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
+ stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_SCALE, ACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCEL_2);
+ stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
} else {
- animatorSetBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, LINEAR);
- animatorSetBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, LINEAR);
+ stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, LINEAR);
+ stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, LINEAR);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index cc58fcf..1b3610a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -81,6 +81,9 @@
private boolean canInterceptTouch() {
if (mCurrentAnimation != null) {
+ mCurrentAnimation.forceFinishIfCloseToEnd();
+ }
+ if (mCurrentAnimation != null) {
// If we are already animating from a previous state, we can intercept.
return true;
}
@@ -126,6 +129,7 @@
for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) {
TaskView view = mRecentsView.getTaskViewAt(i);
+
if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer()
.isEventOverView(view, ev)) {
// Disable swiping up and down if the task overlay is modal.
@@ -214,7 +218,7 @@
if (mCurrentAnimation != null) {
mCurrentAnimation.setOnCancelRunnable(null);
}
- mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation, maxDuration)
+ mCurrentAnimation = mPendingAnimation.createPlaybackController()
.setOnCancelRunnable(this::clearState);
onUserControlledAnimationCreated(mCurrentAnimation);
mCurrentAnimation.getTarget().addListener(this);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
index e1ff4f4..aaf7619 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -48,7 +48,7 @@
*
* @param <T> activity that contains the overview
*/
-final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements
+final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> extends
RemoteAnimationProvider {
private static final long RECENTS_LAUNCH_DURATION = 250;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
index 71580ca..4abb86a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
@@ -213,7 +213,7 @@
@Override
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
// TODO: Remove this once b/77875376 is fixed
- return target.sourceContainerBounds;
+ return target.screenSpaceBounds;
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
index fc50660..c6b719a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
@@ -33,6 +33,7 @@
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -187,7 +188,15 @@
// Otherwise, start overview.
mListener = mActivityInterface.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
- this::createWindowAnimation, mContext, MAIN_EXECUTOR.getHandler(),
+ new RemoteAnimationProvider() {
+ @Override
+ public AnimatorSet createWindowAnimation(
+ RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets) {
+ return RecentsActivityCommand.this.createWindowAnimation(appTargets,
+ wallpaperTargets);
+ }
+ }, mContext, MAIN_EXECUTOR.getHandler(),
mAnimationProvider.getRecentsLaunchDuration());
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
index 681ce02..d9e9cc7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
@@ -50,6 +50,7 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -119,7 +120,7 @@
private void updateSourceStack(RemoteAnimationTargetCompat target) {
mSourceInsets.set(target.contentInsets);
- mSourceStackBounds.set(target.sourceContainerBounds);
+ mSourceStackBounds.set(target.screenSpaceBounds);
// TODO: Should sourceContainerBounds already have this offset?
mSourceStackBounds.offsetTo(target.position.x, target.position.y);
@@ -199,9 +200,17 @@
for (int i = 0; i < params.mTargetSet.unfilteredApps.length; i++) {
RemoteAnimationTargetCompat app = params.mTargetSet.unfilteredApps[i];
SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
- mTmpMatrix.setTranslate(app.position.x, app.position.y);
+ if (app.localBounds != null) {
+ mTmpMatrix.setTranslate(0, 0);
+ if (app.activityType == ACTIVITY_TYPE_HOME && app.mode == MODE_CLOSING) {
+ mTmpMatrix.setTranslate(app.localBounds.left, app.localBounds.top);
+ }
+ } else {
+ mTmpMatrix.setTranslate(app.position.x, app.position.y);
+ }
+
Rect crop = mTmpRect;
- crop.set(app.sourceContainerBounds);
+ crop.set(app.screenSpaceBounds);
crop.offsetTo(0, 0);
float alpha;
float cornerRadius = 0f;
@@ -211,7 +220,11 @@
alpha = mTaskAlphaCallback.getAlpha(app, params.mTargetAlpha);
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
- mTmpMatrix.postTranslate(app.position.x, app.position.y);
+ if (app.localBounds != null) {
+ mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
+ } else {
+ mTmpMatrix.postTranslate(app.position.x, app.position.y);
+ }
mCurrentClipRectF.roundOut(crop);
if (mSupportsRoundedCornersOnWindows) {
if (params.mCornerRadius > -1) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 7e17fbf..9cf45b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -18,9 +18,10 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
-import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
+import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
+import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -33,14 +34,13 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.launcher3.graphics.OverviewScrim;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.DynamicResource;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.plugins.ResourceProvider;
@@ -126,6 +126,8 @@
addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
}
+ mAnimators.play(launcher.getDragLayer().getScrim().createSysuiMultiplierAnim(0f, 1f)
+ .setDuration(ALPHA_DURATION_MS));
mAnimators.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -143,16 +145,20 @@
* Setup workspace with 0 duration to prepare for our staggered animation.
*/
private void prepareToAnimate(Launcher launcher) {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.animFlags = ANIM_ALL_COMPONENTS | SKIP_OVERVIEW;
+ config.duration = 0;
// setRecentsAttachedToAppWindow() will animate recents out.
- launcher.getStateManager().createAtomicAnimation(
- BACKGROUND_APP, NORMAL, builder, ANIM_ALL_COMPONENTS | SKIP_OVERVIEW, 0);
- builder.build().start();
+ launcher.getStateManager().createAtomicAnimation(BACKGROUND_APP, NORMAL, config).start();
// Stop scrolling so that it doesn't interfere with the translation offscreen.
launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
}
+ public AnimatorSet getAnimators() {
+ return mAnimators;
+ }
+
/**
* Starts the animation.
*/
@@ -197,16 +203,12 @@
}
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
- AnimatorSetBuilder scrimAnimBuilder = new AnimatorSetBuilder();
- AnimationConfig scrimAnimConfig = new AnimationConfig();
- scrimAnimConfig.duration = duration;
- PropertySetter scrimPropertySetter = scrimAnimConfig.getPropertySetter(scrimAnimBuilder);
- launcher.getWorkspace().getStateTransitionAnimation().setScrim(scrimPropertySetter, state);
- mAnimators.play(scrimAnimBuilder.build());
- Animator fadeOverviewScrim = ObjectAnimator.ofFloat(
- launcher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
- state.getOverviewScrimAlpha(launcher));
- fadeOverviewScrim.setDuration(duration);
- mAnimators.play(fadeOverviewScrim);
+ PendingAnimation builder = new PendingAnimation(duration, mAnimators);
+ launcher.getWorkspace().getStateTransitionAnimation().setScrim(builder, state);
+ builder.setFloat(
+ launcher.getDragLayer().getOverviewScrim(),
+ OverviewScrim.SCRIM_PROGRESS,
+ state.getOverviewScrimAlpha(launcher),
+ ACCEL_DEACCEL);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index b5e6af4..e15ac46 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -68,7 +68,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.OrientationEventListener;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -88,7 +87,6 @@
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PendingAnimation.EndState;
@@ -96,7 +94,6 @@
import com.android.launcher3.anim.SpringProperty;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
@@ -1165,7 +1162,7 @@
}
private void addDismissedTaskAnimations(View taskView, long duration, PendingAnimation anim) {
- anim.add(ObjectAnimator.ofFloat(taskView, ALPHA, 0).setDuration(duration), ACCEL_2);
+ anim.setViewAlpha(taskView, 0, ACCEL_2);
FloatProperty<View> secondaryViewTranslate =
mOrientationHandler.getSecondaryViewTranslate();
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
@@ -1195,7 +1192,7 @@
if (mPendingAnimation != null) {
mPendingAnimation.finish(false, Touch.SWIPE);
}
- PendingAnimation anim = new PendingAnimation();
+ PendingAnimation anim = new PendingAnimation(duration);
int count = getPageCount();
if (count == 0) {
@@ -1257,9 +1254,7 @@
}
if (needsCurveUpdates) {
- ValueAnimator va = ValueAnimator.ofFloat(0, 1);
- va.addUpdateListener((a) -> updateCurveProperties());
- anim.add(va);
+ anim.addOnFrameCallback(this::updateCurveProperties);
}
// Add a tiny bit of translation Z, so that it draws on top of other views
@@ -1279,6 +1274,7 @@
}
}
+ @SuppressWarnings("WrongCall")
private void onEnd(EndState endState) {
if (endState.isSuccess) {
if (shouldRemoveTask) {
@@ -1290,15 +1286,18 @@
pageToSnapTo == (getTaskViewCount() - 1)) {
pageToSnapTo -= 1;
}
- removeView(taskView);
+ removeViewInLayout(taskView);
if (getTaskViewCount() == 0) {
- removeView(mClearAllButton);
+ removeViewInLayout(mClearAllButton);
hideActionsView();
startHome();
} else {
snapToPageImmediately(pageToSnapTo);
}
+ // Update the layout synchronously so that the position of next view is
+ // immediately available.
+ onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
}
resetTaskVisuals();
mPendingAnimation = null;
@@ -1311,7 +1310,7 @@
if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) {
throw new IllegalStateException("Another pending animation is still running");
}
- PendingAnimation anim = new PendingAnimation();
+ PendingAnimation anim = new PendingAnimation(duration);
int count = getTaskViewCount();
for (int i = 0; i < count; i++) {
@@ -1345,8 +1344,7 @@
}
private void runDismissAnimation(PendingAnimation pendingAnim) {
- AnimatorPlaybackController controller =
- AnimatorPlaybackController.wrap(pendingAnim, DISMISS_TASK_DURATION);
+ AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
controller.dispatchOnStart();
controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE));
controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
@@ -1549,6 +1547,7 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
+
updateEmptyStateUi(changed);
// Set the pivot points to match the task preview center
@@ -1671,7 +1670,7 @@
int count = getTaskViewCount();
if (count == 0) {
- return new PendingAnimation();
+ return new PendingAnimation(duration);
}
int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags();
@@ -1710,10 +1709,9 @@
anim.play(backgroundBlur);
}
anim.play(progressAnim);
- anim.setDuration(duration)
- .setInterpolator(interpolator);
+ anim.setDuration(duration).setInterpolator(interpolator);
- mPendingAnimation = new PendingAnimation();
+ mPendingAnimation = new PendingAnimation(duration);
mPendingAnimation.add(anim);
mPendingAnimation.addEndListener((endState) -> {
if (endState.isSuccess) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 0e1640e..c94b56c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -285,8 +285,7 @@
public AnimatorPlaybackController createLaunchAnimationForRunningTask() {
final PendingAnimation pendingAnimation = getRecentsView().createTaskLaunchAnimation(
this, RECENTS_LAUNCH_DURATION, TOUCH_RESPONSE_INTERPOLATOR);
- AnimatorPlaybackController currentAnimation =
- AnimatorPlaybackController.wrap(pendingAnimation, RECENTS_LAUNCH_DURATION);
+ AnimatorPlaybackController currentAnimation = pendingAnimation.createPlaybackController();
currentAnimation.setEndAction(() -> {
pendingAnimation.finish(true, Touch.SWIPE);
launchTask(false);
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 809543a..a7d00c5 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -52,10 +52,12 @@
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.stream.Stream;
@@ -262,17 +264,21 @@
public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
QuickstepAppTransitionManagerImpl appTransitionManager =
(QuickstepAppTransitionManagerImpl) getAppTransitionManager();
- appTransitionManager.setRemoteAnimationProvider((appTargets, wallpaperTargets) -> {
+ appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
+ @Override
+ public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets) {
- // On the first call clear the reference.
- signal.cancel();
+ // On the first call clear the reference.
+ signal.cancel();
- ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
- fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
- wallpaperTargets));
- AnimatorSet anim = new AnimatorSet();
- anim.play(fadeAnimation);
- return anim;
+ ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
+ fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(appTargets,
+ wallpaperTargets));
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(fadeAnimation);
+ return anim;
+ }
}, signal);
}
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 31c1acf..2cb23f1 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -34,7 +34,8 @@
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@TargetApi(Build.VERSION_CODES.P)
-public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
+public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat,
+ WrappedAnimationRunnerImpl {
private final Handler mHandler;
private final boolean mStartAtFrontOfQueue;
@@ -49,6 +50,10 @@
mStartAtFrontOfQueue = startAtFrontOfQueue;
}
+ public Handler getHandler() {
+ return mHandler;
+ }
+
// Called only in R+ platform
@BinderThread
public void onAnimationStart(RemoteAnimationTargetCompat[] appTargets,
diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java
index 96340b2..fbd7a8a 100644
--- a/quickstep/src/com/android/launcher3/LauncherInitListener.java
+++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3;
+import android.animation.AnimatorSet;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
@@ -25,6 +26,7 @@
import com.android.launcher3.util.ActivityTracker;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate;
@@ -51,17 +53,21 @@
// Set a one-time animation provider. After the first call, this will get cleared.
// TODO: Probably also check the intended target id.
CancellationSignal cancellationSignal = new CancellationSignal();
- appTransitionManager.setRemoteAnimationProvider((appTargets, wallpaperTargets) -> {
+ appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
+ @Override
+ public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets) {
- // On the first call clear the reference.
- cancellationSignal.cancel();
- RemoteAnimationProvider provider = mRemoteAnimationProvider;
- mRemoteAnimationProvider = null;
+ // On the first call clear the reference.
+ cancellationSignal.cancel();
+ RemoteAnimationProvider provider = mRemoteAnimationProvider;
+ mRemoteAnimationProvider = null;
- if (provider != null && launcher.getStateManager().getState().overviewUi) {
- return provider.createWindowAnimation(appTargets, wallpaperTargets);
+ if (provider != null && launcher.getStateManager().getState().overviewUi) {
+ return provider.createWindowAnimation(appTargets, wallpaperTargets);
+ }
+ return null;
}
- return null;
}, cancellationSignal);
}
launcher.deferOverlayCallbacksUntilNextResumeOrStop();
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index f691359..1b39242 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+
import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
@@ -29,6 +31,7 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
import static com.android.launcher3.uioverrides.BackgroundBlurController.BACKGROUND_BLUR;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
@@ -49,6 +52,7 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Matrix;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
@@ -57,6 +61,7 @@
import android.os.Handler;
import android.os.Looper;
import android.util.Pair;
+import android.util.TypedValue;
import android.view.View;
import androidx.annotation.NonNull;
@@ -69,12 +74,14 @@
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.uioverrides.BackgroundBlurController;
+import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.QuickStepContract;
@@ -86,8 +93,6 @@
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.lang.ref.WeakReference;
-
/**
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
* home and/or all-apps. Not used for 3p launchers.
@@ -157,6 +162,7 @@
// Strong refs to runners which are cleared when the launcher activity is destroyed
private WrappedAnimationRunnerImpl mWallpaperOpenRunner;
private WrappedAnimationRunnerImpl mAppLaunchRunner;
+ private WrappedAnimationRunnerImpl mKeyguardGoingAwayRunner;
private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
@Override
@@ -299,8 +305,12 @@
if (mLauncher.isInMultiWindowMode()) {
for (RemoteAnimationTargetCompat target : appTargets) {
if (target.mode == MODE_OPENING) {
- bounds.set(target.sourceContainerBounds);
- bounds.offsetTo(target.position.x, target.position.y);
+ bounds.set(target.screenSpaceBounds);
+ if (target.localBounds != null) {
+ bounds.set(target.localBounds);
+ } else {
+ bounds.offsetTo(target.position.x, target.position.y);
+ }
return bounds;
}
}
@@ -460,6 +470,7 @@
RectF targetBounds = new RectF(windowTargetBounds);
RectF currentBounds = new RectF();
RectF temp = new RectF();
+ Point tmpPos = new Point();
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
@@ -547,6 +558,13 @@
for (int i = appTargets.length - 1; i >= 0; i--) {
RemoteAnimationTargetCompat target = appTargets[i];
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
+
+ tmpPos.set(target.position.x, target.position.y);
+ if (target.localBounds != null) {
+ final Rect localBounds = target.localBounds;
+ tmpPos.set(target.localBounds.left, target.localBounds.top);
+ }
+
if (target.mode == MODE_OPENING) {
matrix.setScale(scale, scale);
matrix.postTranslate(transX0, transY0);
@@ -563,9 +581,9 @@
.withAlpha(1f - mIconAlpha.value)
.withCornerRadius(mWindowRadius.value);
} else {
- matrix.setTranslate(target.position.x, target.position.y);
+ matrix.setTranslate(tmpPos.x, tmpPos.y);
builder.withMatrix(matrix)
- .withWindowCrop(target.sourceContainerBounds)
+ .withWindowCrop(target.screenSpaceBounds)
.withAlpha(1f);
}
builder.withLayer(RemoteAnimationProvider.getLayer(target, MODE_OPENING));
@@ -612,6 +630,17 @@
new WrappedLauncherAnimationRunner<>(mWallpaperOpenRunner,
false /* startAtFrontOfQueue */),
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+
+ if (KEYGUARD_ANIMATION.get()) {
+ mKeyguardGoingAwayRunner = createWallpaperOpenRunner(true /* fromUnlock */);
+ definition.addRemoteAnimation(
+ WindowManagerWrapper.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+ new RemoteAnimationAdapterCompat(
+ new WrappedLauncherAnimationRunner<>(mKeyguardGoingAwayRunner,
+ true /* startAtFrontOfQueue */),
+ CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+ }
+
new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
}
}
@@ -628,6 +657,7 @@
// definition so we don't have to wait for the system gc
mWallpaperOpenRunner = null;
mAppLaunchRunner = null;
+ mKeyguardGoingAwayRunner = null;
}
}
@@ -662,7 +692,7 @@
RemoteAnimationTargetCompat target = appTargets[i];
params[i] = new SurfaceParams.Builder(target.leash)
.withAlpha(1f)
- .withWindowCrop(target.sourceContainerBounds)
+ .withWindowCrop(target.screenSpaceBounds)
.withLayer(RemoteAnimationProvider.getLayer(target, MODE_OPENING))
.withCornerRadius(cornerRadius)
.build();
@@ -681,6 +711,7 @@
SyncRtSurfaceTransactionApplierCompat surfaceApplier =
new SyncRtSurfaceTransactionApplierCompat(mDragLayer);
Matrix matrix = new Matrix();
+ Point tmpPos = new Point();
ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
int duration = CLOSING_TRANSITION_DURATION_MS;
float windowCornerRadius = mDeviceProfile.isMultiWindowMode
@@ -697,22 +728,28 @@
for (int i = appTargets.length - 1; i >= 0; i--) {
RemoteAnimationTargetCompat target = appTargets[i];
SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash);
+
+ tmpPos.set(target.position.x, target.position.y);
+ if (target.localBounds != null) {
+ tmpPos.set(target.localBounds.left, target.localBounds.top);
+ }
+
if (target.mode == MODE_CLOSING) {
matrix.setScale(mScale.value, mScale.value,
- target.sourceContainerBounds.centerX(),
- target.sourceContainerBounds.centerY());
+ target.screenSpaceBounds.centerX(),
+ target.screenSpaceBounds.centerY());
matrix.postTranslate(0, mDy.value);
- matrix.postTranslate(target.position.x, target.position.y);
+ matrix.postTranslate(tmpPos.x, tmpPos.y);
builder.withMatrix(matrix)
.withAlpha(mAlpha.value)
.withCornerRadius(windowCornerRadius);
} else {
- matrix.setTranslate(target.position.x, target.position.y);
+ matrix.setTranslate(tmpPos.x, tmpPos.y);
builder.withMatrix(matrix)
.withAlpha(1f);
}
params[i] = builder
- .withWindowCrop(target.sourceContainerBounds)
+ .withWindowCrop(target.screenSpaceBounds)
.withLayer(RemoteAnimationProvider.getLayer(target, MODE_CLOSING))
.build();
}
@@ -785,52 +822,6 @@
}
/**
- * Used with WrappedLauncherAnimationRunner as an interface for the runner to call back to the
- * implementation.
- */
- protected interface WrappedAnimationRunnerImpl {
- Handler getHandler();
- void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- LauncherAnimationRunner.AnimationResult result);
- }
-
- /**
- * This class is needed to wrap any animation runner that is a part of the
- * RemoteAnimationDefinition:
- * - Launcher creates a new instance of the LauncherAppTransitionManagerImpl whenever it is
- * created, which in turn registers a new definition
- * - When the definition is registered, window manager retains a strong binder reference to the
- * runner passed in
- * - If the Launcher activity is recreated, the new definition registered will replace the old
- * reference in the system's activity record, but until the system server is GC'd, the binder
- * reference will still exist, which references the runner in the Launcher process, which
- * references the (old) Launcher activity through this class
- *
- * Instead we make the runner provided to the definition static only holding a weak reference to
- * the runner implementation. When this animation manager is destroyed, we remove the Launcher
- * reference to the runner, leaving only the weak ref from the runner.
- */
- protected static class WrappedLauncherAnimationRunner<R extends WrappedAnimationRunnerImpl>
- extends LauncherAnimationRunner {
- private WeakReference<R> mImpl;
-
- public WrappedLauncherAnimationRunner(R animationRunnerImpl, boolean startAtFrontOfQueue) {
- super(animationRunnerImpl.getHandler(), startAtFrontOfQueue);
- mImpl = new WeakReference<>(animationRunnerImpl);
- }
-
- @Override
- public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets, AnimationResult result) {
- R animationRunnerImpl = mImpl.get();
- if (animationRunnerImpl != null) {
- animationRunnerImpl.onCreateAnimation(appTargets, wallpaperTargets, result);
- }
- }
- }
-
- /**
* Remote animation runner for animation from the app to Launcher, including recents.
*/
protected class WallpaperOpenLauncherAnimationRunner implements WrappedAnimationRunnerImpl {
@@ -896,18 +887,14 @@
|| mLauncher.isForceInvisible()) {
// Only register the content animation for cancellation when state changes
mLauncher.getStateManager().setCurrentAnimation(anim);
+
if (mFromUnlock) {
- Pair<AnimatorSet, Runnable> contentAnimator =
- getLauncherContentAnimator(false /* isAppOpening */,
- new float[] {mContentTransY, 0});
- contentAnimator.first.setStartDelay(0);
- anim.play(contentAnimator.first);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- contentAnimator.second.run();
- }
- });
+ float velocityDpPerS = DynamicResource.provider(mLauncher)
+ .getDimension(R.dimen.unlock_staggered_velocity_dp_per_s);
+ float velocityPxPerS = TypedValue.applyDimension(COMPLEX_UNIT_DIP,
+ velocityDpPerS, mLauncher.getResources().getDisplayMetrics());
+ anim.play(new StaggeredWorkspaceAnim(mLauncher, velocityPxPerS, false)
+ .getAnimators());
} else {
createLauncherResumeAnimation(anim);
}
diff --git a/quickstep/src/com/android/launcher3/WrappedAnimationRunnerImpl.java b/quickstep/src/com/android/launcher3/WrappedAnimationRunnerImpl.java
new file mode 100644
index 0000000..da2aee4
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/WrappedAnimationRunnerImpl.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+import android.os.Handler;
+
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+/**
+ * Used with WrappedLauncherAnimationRunner as an interface for the runner to call back to the
+ * implementation.
+ */
+public interface WrappedAnimationRunnerImpl {
+ Handler getHandler();
+ void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets,
+ LauncherAnimationRunner.AnimationResult result);
+}
diff --git a/quickstep/src/com/android/launcher3/WrappedLauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/WrappedLauncherAnimationRunner.java
new file mode 100644
index 0000000..1753b62
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/WrappedLauncherAnimationRunner.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This class is needed to wrap any animation runner that is a part of the
+ * RemoteAnimationDefinition:
+ * - Launcher creates a new instance of the LauncherAppTransitionManagerImpl whenever it is
+ * created, which in turn registers a new definition
+ * - When the definition is registered, window manager retains a strong binder reference to the
+ * runner passed in
+ * - If the Launcher activity is recreated, the new definition registered will replace the old
+ * reference in the system's activity record, but until the system server is GC'd, the binder
+ * reference will still exist, which references the runner in the Launcher process, which
+ * references the (old) Launcher activity through this class
+ *
+ * Instead we make the runner provided to the definition static only holding a weak reference to
+ * the runner implementation. When this animation manager is destroyed, we remove the Launcher
+ * reference to the runner, leaving only the weak ref from the runner.
+ */
+public class WrappedLauncherAnimationRunner<R extends WrappedAnimationRunnerImpl>
+ extends LauncherAnimationRunner {
+ private WeakReference<R> mImpl;
+
+ public WrappedLauncherAnimationRunner(R animationRunnerImpl, boolean startAtFrontOfQueue) {
+ super(animationRunnerImpl.getHandler(), startAtFrontOfQueue);
+ mImpl = new WeakReference<>(animationRunnerImpl);
+ }
+
+ @Override
+ public void onCreateAnimation(RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets, AnimationResult result) {
+ R animationRunnerImpl = mImpl.get();
+ if (animationRunnerImpl != null) {
+ animationRunnerImpl.onCreateAnimation(appTargets, wallpaperTargets, result);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java b/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
index 671aab0..e82a504 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
@@ -16,19 +16,23 @@
package com.android.launcher3.uioverrides;
-import android.animation.ValueAnimator;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.quickstep.AnimatedFloat.VALUE;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.UiThreadHelper;
+import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SystemUiProxy;
public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler {
private final BaseQuickstepLauncher mLauncher;
+ private final AnimatedFloat mBackAlpha = new AnimatedFloat(this::updateBackAlpha);
public BackButtonAlphaHandler(BaseQuickstepLauncher launcher) {
mLauncher = launcher;
@@ -38,8 +42,8 @@
public void setState(LauncherState state) { }
@Override
- public void setStateWithAnimation(LauncherState toState,
- AnimatorSetBuilder builder, LauncherStateManager.AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
+ PendingAnimation animation) {
if (config.onlyPlayAtomicComponent()) {
return;
}
@@ -51,17 +55,12 @@
return;
}
- float fromAlpha = SystemUiProxy.INSTANCE.get(mLauncher).getLastBackButtonAlpha();
- float toAlpha = toState.hideBackButton ? 0 : 1;
- if (Float.compare(fromAlpha, toAlpha) != 0) {
- ValueAnimator anim = ValueAnimator.ofFloat(fromAlpha, toAlpha);
- anim.setDuration(config.duration);
- anim.addUpdateListener(valueAnimator -> {
- final float alpha = (float) valueAnimator.getAnimatedValue();
- UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
- BaseQuickstepLauncher.SET_BACK_BUTTON_ALPHA, alpha, false /* animate */);
- });
- builder.play(anim);
- }
+ mBackAlpha.value = SystemUiProxy.INSTANCE.get(mLauncher).getLastBackButtonAlpha();
+ animation.setFloat(mBackAlpha, VALUE, toState.hideBackButton ? 0 : 1, LINEAR);
+ }
+
+ private void updateBackAlpha() {
+ UiThreadHelper.setBackButtonAlphaAsync(mLauncher,
+ BaseQuickstepLauncher.SET_BACK_BUTTON_ALPHA, mBackAlpha.value, false /* animate */);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BackgroundBlurController.java b/quickstep/src/com/android/launcher3/uioverrides/BackgroundBlurController.java
index 022a5f7..513310e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BackgroundBlurController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BackgroundBlurController.java
@@ -26,8 +26,8 @@
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SurfaceControlCompat;
import com.android.systemui.shared.system.TransactionCompat;
@@ -133,16 +133,15 @@
}
@Override
- public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
- LauncherStateManager.AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
+ PendingAnimation animation) {
if (mSurface == null || config.onlyPlayAtomicComponent()) {
return;
}
int toBackgroundBlurRadius = toState.getBackgroundBlurRadius(mLauncher);
if (mBackgroundBlurRadius != toBackgroundBlurRadius) {
- PropertySetter propertySetter = config.getPropertySetter(builder);
- propertySetter.setInt(this, BACKGROUND_BLUR, toBackgroundBlurRadius, LINEAR);
+ animation.setInt(this, BACKGROUND_BLUR, toBackgroundBlurRadius, LINEAR);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 94e67f0..03454f7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -20,17 +20,17 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
-import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_PEEK;
-import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_SCALE;
-import static com.android.launcher3.LauncherStateManager.SKIP_OVERVIEW;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCRIM_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import android.util.FloatProperty;
import android.view.View;
@@ -41,11 +41,10 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.graphics.OverviewScrim;
+import com.android.launcher3.states.StateAnimationConfig;
/**
* State handler for recents view. Manages UI changes and animations for recents view based off the
@@ -86,8 +85,8 @@
}
@Override
- public final void setStateWithAnimation(@NonNull final LauncherState toState,
- @NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
+ public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
+ PendingAnimation builder) {
if (!config.hasAnimationFlag(PLAY_ATOMIC_OVERVIEW_PEEK | PLAY_ATOMIC_OVERVIEW_SCALE)) {
// The entire recents animation is played atomically.
return;
@@ -95,25 +94,24 @@
if (config.hasAnimationFlag(SKIP_OVERVIEW)) {
return;
}
- setStateWithAnimationInternal(toState, builder, config);
+ setStateWithAnimationInternal(toState, config, builder);
}
/**
* Core logic for animating the recents view UI.
*
* @param toState state to animate to
- * @param builder animator set builder
* @param config current animation config
+ * @param setter animator set builder
*/
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
- @NonNull AnimatorSetBuilder builder, @NonNull AnimationConfig config) {
- PropertySetter setter = config.getPropertySetter(builder);
+ @NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) {
ScaleAndTranslation scaleAndTranslation = toState.getOverviewScaleAndTranslation(mLauncher);
- Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
+ Interpolator scaleInterpolator = config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR);
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndTranslation.scale, scaleInterpolator);
- Interpolator translateXInterpolator = builder.getInterpolator(
+ Interpolator translateXInterpolator = config.getInterpolator(
ANIM_OVERVIEW_TRANSLATE_X, LINEAR);
- Interpolator translateYInterpolator = builder.getInterpolator(
+ Interpolator translateYInterpolator = config.getInterpolator(
ANIM_OVERVIEW_TRANSLATE_Y, LINEAR);
float translationX = scaleAndTranslation.translationX;
if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
@@ -123,14 +121,14 @@
setter.setFloat(mRecentsView, VIEW_TRANSLATE_Y, scaleAndTranslation.translationY,
translateYInterpolator);
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
- builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
+ config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
- builder.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
+ config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
if (mActionsView != null) {
setter.setFloat(mActionsView, VIEW_TRANSLATE_X, translationX, translateXInterpolator);
setter.setFloat(mActionsView, VIEW_ALPHA, toState.overviewUi ? 1 : 0,
- builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
+ config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java b/quickstep/src/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java
new file mode 100644
index 0000000..548223a
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java
@@ -0,0 +1,45 @@
+/*
+ * 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.uioverrides;
+
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Size;
+import android.view.View;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.graphics.LauncherPreviewRenderer;
+import com.android.systemui.shared.system.SurfaceViewRequestReceiver;
+
+/** Render preview using surface view. */
+public class PreviewSurfaceRenderer {
+
+ /** Handle a received surface view request. */
+ public static void render(Context context, Bundle bundle) {
+ final String gridName = bundle.getString("name");
+ bundle.remove("name");
+ final InvariantDeviceProfile idp = new InvariantDeviceProfile(context, gridName);
+
+ MAIN_EXECUTOR.execute(() -> {
+ View view = new LauncherPreviewRenderer(context, idp).getRenderedView();
+ new SurfaceViewRequestReceiver().onReceive(context, bundle, view,
+ new Size(view.getMeasuredWidth(), view.getMeasuredHeight()));
+ });
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
index 3d0fc56..bef191e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
@@ -9,7 +9,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationFlags;
+import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index a060d64..cc3fd97 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -19,13 +19,13 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.TimeInterpolator;
@@ -37,11 +37,10 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationFlags;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.uioverrides.states.OverviewState;
@@ -148,16 +147,16 @@
return isTouchOverHotseat(mLauncher, ev) ? ContainerType.HOTSEAT : ContainerType.WORKSPACE;
}
- private AnimatorSetBuilder getNormalToOverviewAnimation() {
+ private StateAnimationConfig getNormalToOverviewAnimation() {
mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR;
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ StateAnimationConfig builder = new StateAnimationConfig();
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper);
return builder;
}
- public static AnimatorSetBuilder getOverviewToAllAppsAnimation() {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ private static StateAnimationConfig getOverviewToAllAppsAnimation() {
+ StateAnimationConfig builder = new StateAnimationConfig();
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
builder.setInterpolator(ANIM_OVERVIEW_FADE, Interpolators.clampToProgress(DEACCEL,
@@ -165,8 +164,8 @@
return builder;
}
- private AnimatorSetBuilder getAllAppsToOverviewAnimation() {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ private StateAnimationConfig getAllAppsToOverviewAnimation() {
+ StateAnimationConfig builder = new StateAnimationConfig();
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
builder.setInterpolator(ANIM_OVERVIEW_FADE, Interpolators.clampToProgress(ACCEL,
@@ -174,41 +173,42 @@
return builder;
}
- private AnimatorSetBuilder getNormalToAllAppsAnimation() {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ private StateAnimationConfig getNormalToAllAppsAnimation() {
+ StateAnimationConfig builder = new StateAnimationConfig();
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
0, ALL_APPS_CONTENT_FADE_THRESHOLD));
return builder;
}
- private AnimatorSetBuilder getAllAppsToNormalAnimation() {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ private StateAnimationConfig getAllAppsToNormalAnimation() {
+ StateAnimationConfig builder = new StateAnimationConfig();
builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
1 - ALL_APPS_CONTENT_FADE_THRESHOLD, 1));
return builder;
}
@Override
- protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
- LauncherState toState) {
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
+ protected StateAnimationConfig getConfigForStates(
+ LauncherState fromState, LauncherState toState) {
+ final StateAnimationConfig config;
if (fromState == NORMAL && toState == OVERVIEW) {
- builder = getNormalToOverviewAnimation();
+ config = getNormalToOverviewAnimation();
} else if (fromState == OVERVIEW && toState == ALL_APPS) {
- builder = getOverviewToAllAppsAnimation();
+ config = getOverviewToAllAppsAnimation();
} else if (fromState == ALL_APPS && toState == OVERVIEW) {
- builder = getAllAppsToOverviewAnimation();
+ config = getAllAppsToOverviewAnimation();
} else if (fromState == NORMAL && toState == ALL_APPS) {
- builder = getNormalToAllAppsAnimation();
+ config = getNormalToAllAppsAnimation();
} else if (fromState == ALL_APPS && toState == NORMAL) {
- builder = getAllAppsToNormalAnimation();
+ config = getAllAppsToNormalAnimation();
+ } else {
+ config = new StateAnimationConfig();
}
- return builder;
+ return config;
}
@Override
- protected float initCurrentAnimation(@AnimationFlags int animComponents) {
- animComponents = updateAnimComponentsOnReinit(animComponents);
+ protected float initCurrentAnimation(@AnimationFlags int animFlags) {
float range = getShiftRange();
long maxAccuracy = (long) (2 * range);
@@ -217,8 +217,10 @@
float totalShift = endVerticalShift - startVerticalShift;
- final AnimatorSetBuilder builder = totalShift == 0 ? new AnimatorSetBuilder()
- : getAnimatorSetBuilderForStates(mFromState, mToState);
+ final StateAnimationConfig config = totalShift == 0 ? new StateAnimationConfig()
+ : getConfigForStates(mFromState, mToState);
+ config.animFlags = updateAnimComponentsOnReinit(animFlags);
+ config.duration = maxAccuracy;
cancelPendingAnim();
@@ -232,15 +234,15 @@
cancelPendingAnim();
clearState();
};
- mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation, maxAccuracy)
+ mCurrentAnimation = mPendingAnimation.createPlaybackController()
.setOnCancelRunnable(onCancelRunnable);
mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation);
totalShift = LayoutUtils.getShelfTrackingDistance(mLauncher,
mLauncher.getDeviceProfile());
} else {
mCurrentAnimation = mLauncher.getStateManager()
- .createAnimationToNewWorkspace(mToState, builder, maxAccuracy, this::clearState,
- animComponents);
+ .createAnimationToNewWorkspace(mToState, config)
+ .setOnCancelRunnable(this::clearState);
}
if (totalShift == 0) {
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
index 6520c4f..21b97ec 100644
--- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
@@ -21,21 +21,22 @@
import android.os.Handler;
import com.android.launcher3.LauncherAnimationRunner;
+import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
-@FunctionalInterface
-public interface RemoteAnimationProvider {
+public abstract class RemoteAnimationProvider {
+ LauncherAnimationRunner mAnimationRunner;
static final int Z_BOOST_BASE = 800570000;
- AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
+ public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets);
- default ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
- LauncherAnimationRunner runner = new LauncherAnimationRunner(handler,
+ ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
+ mAnimationRunner = new LauncherAnimationRunner(handler,
false /* startAtFrontOfQueue */) {
@Override
@@ -44,8 +45,11 @@
result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
}
};
+ final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner(
+ mAnimationRunner, false /* startAtFrontOfQueue */);
+
return ActivityOptionsCompat.makeRemoteAnimation(
- new RemoteAnimationAdapterCompat(runner, duration, 0));
+ new RemoteAnimationAdapterCompat(wrapper, duration, 0));
}
/**
@@ -63,7 +67,7 @@
}
}
- static int getLayer(RemoteAnimationTargetCompat target, int boostModeTarget) {
+ public static int getLayer(RemoteAnimationTargetCompat target, int boostModeTarget) {
return target.mode == boostModeTarget
? Z_BOOST_BASE + target.prefixOrderIndex
: target.prefixOrderIndex;
@@ -72,7 +76,7 @@
/**
* @return the target with the lowest opaque layer for a certain app animation, or null.
*/
- static RemoteAnimationTargetCompat findLowestOpaqueLayerTarget(
+ public static RemoteAnimationTargetCompat findLowestOpaqueLayerTarget(
RemoteAnimationTargetCompat[] appTargets, int mode) {
int lowestLayer = Integer.MAX_VALUE;
int lowestLayerIndex = -1;
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index 4ac815e..0afe4a8 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -166,12 +166,9 @@
return false;
}
- setOverlayPackageEnabled(NAV_BAR_MODE_3BUTTON_OVERLAY,
- overlayPackage == NAV_BAR_MODE_3BUTTON_OVERLAY);
- setOverlayPackageEnabled(NAV_BAR_MODE_2BUTTON_OVERLAY,
- overlayPackage == NAV_BAR_MODE_2BUTTON_OVERLAY);
- setOverlayPackageEnabled(NAV_BAR_MODE_GESTURAL_OVERLAY,
- overlayPackage == NAV_BAR_MODE_GESTURAL_OVERLAY);
+ Log.d(TAG, "setActiveOverlay: " + overlayPackage + "...");
+ UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+ "cmd overlay enable-exclusive " + overlayPackage);
if (currentSysUiNavigationMode() != expectedMode) {
final CountDownLatch latch = new CountDownLatch(1);
@@ -210,14 +207,6 @@
return true;
}
- private static void setOverlayPackageEnabled(String overlayPackage, boolean enable)
- throws Exception {
- Log.d(TAG, "setOverlayPackageEnabled: " + overlayPackage + " " + enable);
- final String action = enable ? "enable" : "disable";
- UiDevice.getInstance(getInstrumentation()).executeShellCommand(
- "cmd overlay " + action + " " + overlayPackage);
- }
-
private static boolean packageExists(String packageName) {
try {
PackageManager pm = getInstrumentation().getContext().getPackageManager();
diff --git a/res/values/config.xml b/res/values/config.xml
index df0f233..6c239bd 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -142,6 +142,7 @@
<item name="staggered_damping_ratio" type="dimen" format="float">0.7</item>
<item name="staggered_stiffness" type="dimen" format="float">150</item>
+ <dimen name="unlock_staggered_velocity_dp_per_s">3dp</dimen>
<!-- Swipe up to home related -->
<dimen name="swipe_up_fling_min_visible_change">18dp</dimen>
@@ -170,6 +171,7 @@
<item>@dimen/staggered_damping_ratio</item>
<item>@dimen/staggered_stiffness</item>
+ <item>@dimen/unlock_staggered_velocity_dp_per_s</item>
<item>@dimen/swipe_up_fling_min_visible_change</item>
<item>@dimen/swipe_up_y_overshoot</item>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9d0fb56..7748b3a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -208,7 +208,7 @@
<string name="notification_dots_service_title">Show notification dots</string>
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=40] -->
- <string name="auto_add_shortcuts_label">Add icon to Home screen</string>
+ <string name="auto_add_shortcuts_label">Add app icons to Home screen</string>
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
<string name="auto_add_shortcuts_description">For new apps</string>
diff --git a/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
new file mode 100644
index 0000000..8f58d8b
--- /dev/null
+++ b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskV2Test.java
@@ -0,0 +1,155 @@
+/*
+ * 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.model;
+
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+import static com.android.launcher3.LauncherSettings.Favorites.TMP_CONTENT_URI;
+import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+import static com.android.launcher3.util.LauncherModelHelper.APP_ICON;
+import static com.android.launcher3.util.LauncherModelHelper.DESKTOP;
+import static com.android.launcher3.util.LauncherModelHelper.HOTSEAT;
+import static com.android.launcher3.util.LauncherModelHelper.SHORTCUT;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Point;
+import android.os.Process;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.LauncherModelHelper;
+import com.android.launcher3.util.LauncherRoboTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.HashSet;
+
+/** Unit tests for {@link GridSizeMigrationTaskV2} */
+@RunWith(LauncherRoboTestRunner.class)
+public class GridSizeMigrationTaskV2Test {
+
+ private LauncherModelHelper mModelHelper;
+ private Context mContext;
+ private SQLiteDatabase mDb;
+
+ private HashSet<String> mValidPackages;
+ private InvariantDeviceProfile mIdp;
+
+ @Before
+ public void setUp() {
+ mModelHelper = new LauncherModelHelper();
+ mContext = RuntimeEnvironment.application;
+ mDb = mModelHelper.provider.getDb();
+
+ mValidPackages = new HashSet<>();
+ mValidPackages.add(TEST_PACKAGE);
+ mIdp = InvariantDeviceProfile.INSTANCE.get(mContext);
+
+ long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser(
+ Process.myUserHandle());
+ dropTable(mDb, LauncherSettings.Favorites.TMP_TABLE);
+ LauncherSettings.Favorites.addTableToDb(mDb, userSerial, false,
+ LauncherSettings.Favorites.TMP_TABLE);
+ }
+
+ @Test
+ public void testMigration() {
+ final String testPackage1 = "com.android.launcher3.validpackage1";
+ final String testPackage2 = "com.android.launcher3.validpackage2";
+ final String testPackage3 = "com.android.launcher3.validpackage3";
+ final String testPackage4 = "com.android.launcher3.validpackage4";
+ final String testPackage5 = "com.android.launcher3.validpackage5";
+ final String testPackage7 = "com.android.launcher3.validpackage7";
+
+ mValidPackages.add(testPackage1);
+ mValidPackages.add(testPackage2);
+ mValidPackages.add(testPackage3);
+ mValidPackages.add(testPackage4);
+ mValidPackages.add(testPackage5);
+ mValidPackages.add(testPackage7);
+
+ int[] srcHotseatItems = {
+ mModelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
+ mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
+ -1,
+ mModelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
+ mModelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI),
+ };
+ mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage5, 5, TMP_CONTENT_URI);
+
+ int[] destHotseatItems = {
+ -1,
+ mModelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2),
+ -1,
+ };
+ mModelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage7);
+
+ mIdp.numHotseatIcons = 3;
+ mIdp.numColumns = 3;
+ mIdp.numRows = 3;
+ GridSizeMigrationTaskV2.DbReader srcReader = new GridSizeMigrationTaskV2.DbReader(mDb,
+ LauncherSettings.Favorites.TMP_TABLE, mContext, mValidPackages, 5);
+ GridSizeMigrationTaskV2.DbReader destReader = new GridSizeMigrationTaskV2.DbReader(mDb,
+ LauncherSettings.Favorites.TABLE_NAME, mContext, mValidPackages, 3);
+ GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(mContext, mDb, srcReader,
+ destReader, 3, new Point(mIdp.numColumns, mIdp.numRows));
+ task.migrate();
+
+ Cursor c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ new String[]{LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.INTENT},
+ "container=" + CONTAINER_HOTSEAT, null, null, null);
+ assertEquals(c.getCount(), 3);
+ int screenIndex = c.getColumnIndex(LauncherSettings.Favorites.SCREEN);
+ int intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
+ c.moveToNext();
+ assertEquals(c.getInt(screenIndex), 1);
+ assertTrue(c.getString(intentIndex).contains(testPackage2));
+ c.moveToNext();
+ assertEquals(c.getInt(screenIndex), 0);
+ assertTrue(c.getString(intentIndex).contains(testPackage1));
+ c.moveToNext();
+ assertEquals(c.getInt(screenIndex), 2);
+ assertTrue(c.getString(intentIndex).contains(testPackage3));
+ c.close();
+
+ c = mContext.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
+ new String[]{LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,
+ LauncherSettings.Favorites.INTENT},
+ "container=" + CONTAINER_DESKTOP, null, null, null);
+ assertEquals(c.getCount(), 2);
+ intentIndex = c.getColumnIndex(LauncherSettings.Favorites.INTENT);
+ int cellXIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLX);
+ int cellYIndex = c.getColumnIndex(LauncherSettings.Favorites.CELLY);
+
+ c.moveToNext();
+ assertTrue(c.getString(intentIndex).contains(testPackage7));
+ c.moveToNext();
+ assertTrue(c.getString(intentIndex).contains(testPackage5));
+ assertEquals(c.getInt(cellXIndex), 0);
+ assertEquals(c.getInt(cellYIndex), 2);
+ }
+}
diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java b/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
index e133cf2..20b1453 100644
--- a/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/robolectric_tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -230,7 +230,21 @@
}
public int addItem(int type, int screen, int container, int x, int y) {
- return addItem(type, screen, container, x, y, mDefaultProfileId);
+ return addItem(type, screen, container, x, y, mDefaultProfileId, TEST_PACKAGE);
+ }
+
+ public int addItem(int type, int screen, int container, int x, int y, long profileId) {
+ return addItem(type, screen, container, x, y, profileId, TEST_PACKAGE);
+ }
+
+ public int addItem(int type, int screen, int container, int x, int y, String packageName) {
+ return addItem(type, screen, container, x, y, mDefaultProfileId, packageName);
+ }
+
+ public int addItem(int type, int screen, int container, int x, int y, String packageName,
+ int id, Uri contentUri) {
+ addItem(type, screen, container, x, y, mDefaultProfileId, packageName, id, contentUri);
+ return id;
}
/**
@@ -238,11 +252,19 @@
* @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
* folder (where the type represents the number of items in the folder).
*/
- public int addItem(int type, int screen, int container, int x, int y, long profileId) {
+ public int addItem(int type, int screen, int container, int x, int y, long profileId,
+ String packageName) {
Context context = RuntimeEnvironment.application;
int id = LauncherSettings.Settings.call(context.getContentResolver(),
LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
.getInt(LauncherSettings.Settings.EXTRA_VALUE);
+ addItem(type, screen, container, x, y, profileId, packageName, id, CONTENT_URI);
+ return id;
+ }
+
+ public void addItem(int type, int screen, int container, int x, int y, long profileId,
+ String packageName, int id, Uri contentUri) {
+ Context context = RuntimeEnvironment.application;
ContentValues values = new ContentValues();
values.put(LauncherSettings.Favorites._ID, id);
@@ -257,7 +279,7 @@
if (type == APP_ICON || type == SHORTCUT) {
values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
values.put(LauncherSettings.Favorites.INTENT,
- new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0));
+ new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
} else {
values.put(LauncherSettings.Favorites.ITEM_TYPE,
LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
@@ -267,8 +289,7 @@
}
}
- context.getContentResolver().insert(CONTENT_URI, values);
- return id;
+ context.getContentResolver().insert(contentUri, values);
}
public int[][][] createGrid(int[][][] typeArray) {
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index af2cdc3..12b5fc1 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -22,7 +22,6 @@
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
-import android.animation.Animator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
@@ -30,11 +29,12 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.TouchController;
@@ -134,9 +134,8 @@
* Creates a user-controlled animation to hint that the view will be closed if completed.
* @param distanceToMove The max distance that elements should move from their starting point.
*/
- public @Nullable Animator createHintCloseAnim(float distanceToMove) {
- return null;
- }
+ public void addHintCloseAnim(
+ float distanceToMove, Interpolator interpolator, PendingAnimation target) { }
public abstract void logActionCommand(int command);
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 697048a..a699c32 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -17,6 +17,7 @@
package com.android.launcher3;
import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO;
+import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -164,8 +165,11 @@
return false;
}
- mOpenHelper.close();
+ DatabaseHelper oldHelper = mOpenHelper;
mOpenHelper = new DatabaseHelper(getContext());
+ copyTable(oldHelper.getReadableDatabase(), Favorites.TABLE_NAME,
+ mOpenHelper.getWritableDatabase(), Favorites.TMP_TABLE, getContext());
+ oldHelper.close();
return true;
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 216c221..f516446 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -103,6 +103,11 @@
public static final String PREVIEW_TABLE_NAME = "favorites_preview";
/**
+ * Temporary table used specifically for multi-db grid migrations
+ */
+ public static final String TMP_TABLE = "favorites_tmp";
+
+ /**
* The content:// style URL for "favorites" table
*/
public static final Uri CONTENT_URI = Uri.parse("content://"
@@ -115,6 +120,12 @@
+ LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME);
/**
+ * The content:// style URL for "favorites_tmp" table
+ */
+ public static final Uri TMP_CONTENT_URI = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + TMP_TABLE);
+
+ /**
* The content:// style URL for a given row, identified by its id.
*
* @param id The row id.
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 62b8927..df71f16 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -20,11 +20,6 @@
import static android.view.View.VISIBLE;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
@@ -32,6 +27,11 @@
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.states.RotationHelper.REQUEST_NONE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
@@ -46,9 +46,9 @@
import android.view.animation.Interpolator;
import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.states.HintState;
import com.android.launcher3.states.SpringLoadedState;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.uioverrides.states.AllAppsState;
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -325,13 +325,13 @@
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
*/
public void prepareForAtomicAnimation(Launcher launcher, LauncherState fromState,
- AnimatorSetBuilder builder) {
+ StateAnimationConfig config) {
if (this == NORMAL && fromState == OVERVIEW) {
- builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
- builder.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
- builder.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
- builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
- builder.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
+ config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
+ config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
+ config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
+ config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
Workspace workspace = launcher.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
@@ -363,7 +363,7 @@
}
} else if (this == NORMAL && fromState == OVERVIEW_PEEK) {
// Keep fully visible until the very end (when overview is offscreen) to make invisible.
- builder.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
+ config.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1);
}
}
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index 04134f2..24d0c41 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -17,26 +17,23 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.os.Handler;
import android.os.Looper;
-import androidx.annotation.IntDef;
-
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
+import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
/**
@@ -84,28 +81,7 @@
public static final String TAG = "StateManager";
- // We separate the state animations into "atomic" and "non-atomic" components. The atomic
- // components may be run atomically - that is, all at once, instead of user-controlled. However,
- // atomic components are not restricted to this purpose; they can be user-controlled alongside
- // non atomic components as well. Note that each gesture model has exactly one atomic component,
- // PLAY_ATOMIC_OVERVIEW_SCALE *or* PLAY_ATOMIC_OVERVIEW_PEEK.
- @IntDef(flag = true, value = {
- PLAY_NON_ATOMIC,
- PLAY_ATOMIC_OVERVIEW_SCALE,
- PLAY_ATOMIC_OVERVIEW_PEEK,
- SKIP_OVERVIEW,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface AnimationFlags {}
- public static final int PLAY_NON_ATOMIC = 1 << 0;
- public static final int PLAY_ATOMIC_OVERVIEW_SCALE = 1 << 1;
- public static final int PLAY_ATOMIC_OVERVIEW_PEEK = 1 << 2;
- public static final int SKIP_OVERVIEW = 1 << 3;
-
- public static final int ANIM_ALL_COMPONENTS = PLAY_NON_ATOMIC | PLAY_ATOMIC_OVERVIEW_SCALE
- | PLAY_ATOMIC_OVERVIEW_PEEK;
-
- private final AnimationConfig mConfig = new AnimationConfig();
+ private final AnimationState mConfig = new AnimationState();
private final Handler mUiHandler;
private final Launcher mLauncher;
private final ArrayList<StateListener> mListeners = new ArrayList<>();
@@ -140,7 +116,7 @@
writer.println(prefix + "\tmCurrentStableState:" + mCurrentStableState);
writer.println(prefix + "\tmState:" + mState);
writer.println(prefix + "\tmRestState:" + mRestState);
- writer.println(prefix + "\tisInTransition:" + (mConfig.mCurrentAnimation != null));
+ writer.println(prefix + "\tisInTransition:" + (mConfig.currentAnimation != null));
}
public StateHandler[] getStateHandlers() {
@@ -171,7 +147,7 @@
*/
public boolean isInStableState(LauncherState state) {
return mState == state && mCurrentStableState == state
- && (mConfig.mTargetState == null || mConfig.mTargetState == state);
+ && (mConfig.targetState == null || mConfig.targetState == state);
}
/**
@@ -218,12 +194,12 @@
}
public void reapplyState(boolean cancelCurrentAnimation) {
- boolean wasInAnimation = mConfig.mCurrentAnimation != null;
+ boolean wasInAnimation = mConfig.currentAnimation != null;
if (cancelCurrentAnimation) {
cancelAllStateElementAnimation();
cancelAnimation();
}
- if (mConfig.mCurrentAnimation == null) {
+ if (mConfig.currentAnimation == null) {
for (StateHandler handler : getStateHandlers()) {
handler.setState(mState);
}
@@ -237,16 +213,16 @@
final Runnable onCompleteRunnable) {
animated &= Utilities.areAnimationsEnabled(mLauncher);
if (mLauncher.isInState(state)) {
- if (mConfig.mCurrentAnimation == null) {
+ if (mConfig.currentAnimation == null) {
// Run any queued runnable
if (onCompleteRunnable != null) {
onCompleteRunnable.run();
}
return;
- } else if (!mConfig.userControlled && animated && mConfig.mTargetState == state) {
+ } else if (!mConfig.userControlled && animated && mConfig.targetState == state) {
// We are running the same animation as requested
if (onCompleteRunnable != null) {
- mConfig.mCurrentAnimation.addListener(
+ mConfig.currentAnimation.addListener(
AnimationSuccessListener.forRunnable(onCompleteRunnable));
}
return;
@@ -276,9 +252,9 @@
if (delay > 0) {
// Create the animation after the delay as some properties can change between preparing
// the animation and running the animation.
- int startChangeId = mConfig.mChangeId;
+ int startChangeId = mConfig.changeId;
mUiHandler.postDelayed(() -> {
- if (mConfig.mChangeId == startChangeId) {
+ if (mConfig.changeId == startChangeId) {
goToStateAnimated(state, fromState, onCompleteRunnable);
}
}, delay);
@@ -294,11 +270,11 @@
mConfig.duration = state == NORMAL
? fromState.getTransitionDuration(mLauncher)
: state.getTransitionDuration(mLauncher);
-
- AnimatorSetBuilder builder = new AnimatorSetBuilder();
- prepareForAtomicAnimation(fromState, state, builder);
- AnimatorSet animation = createAnimationToNewWorkspaceInternal(
- state, builder, onCompleteRunnable);
+ prepareForAtomicAnimation(fromState, state, mConfig);
+ AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).getAnim();
+ if (onCompleteRunnable != null) {
+ animation.addListener(AnimationSuccessListener.forRunnable(onCompleteRunnable));
+ }
mUiHandler.post(new StartAnimRunnable(animation));
}
@@ -308,44 +284,22 @@
* - Setting some start values (e.g. scale) for views that are hidden but about to be shown.
*/
public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
- AnimatorSetBuilder builder) {
- toState.prepareForAtomicAnimation(mLauncher, fromState, builder);
- }
-
- public AnimatorSet createAtomicAnimation(LauncherState fromState, LauncherState toState,
- AnimatorSetBuilder builder, @AnimationFlags int animFlags, long duration) {
- prepareForAtomicAnimation(fromState, toState, builder);
- AnimationConfig config = new AnimationConfig();
- config.mAnimFlags = animFlags;
- config.duration = duration;
- for (StateHandler handler : mLauncher.getStateManager().getStateHandlers()) {
- handler.setStateWithAnimation(toState, builder, config);
- }
- return builder.build();
+ StateAnimationConfig config) {
+ toState.prepareForAtomicAnimation(mLauncher, fromState, config);
}
/**
- * Creates a {@link AnimatorPlaybackController} that can be used for a controlled
- * state transition. The UI is force-set to fromState before creating the controller.
- * @param fromState the initial state for the transition.
- * @param state the final state for the transition.
- * @param duration intended duration for normal playback. Use higher duration for better
- * accuracy.
+ * Creates an animation representing atomic transitions between the provided states
*/
- public AnimatorPlaybackController createAnimationToNewWorkspace(
- LauncherState fromState, LauncherState state, long duration) {
- // Since we are creating a state animation to a different state, temporarily prevent state
- // change as part of config reset.
- LauncherState originalRestState = mRestState;
- mRestState = state;
- mConfig.reset();
- mRestState = originalRestState;
+ public AnimatorSet createAtomicAnimation(
+ LauncherState fromState, LauncherState toState, StateAnimationConfig config) {
+ PendingAnimation builder = new PendingAnimation(config.duration);
+ prepareForAtomicAnimation(fromState, toState, config);
- for (StateHandler handler : getStateHandlers()) {
- handler.setState(fromState);
+ for (StateHandler handler : mLauncher.getStateManager().getStateHandlers()) {
+ handler.setStateWithAnimation(toState, config, builder);
}
-
- return createAnimationToNewWorkspace(state, duration);
+ return builder.getAnim();
}
/**
@@ -362,32 +316,27 @@
public AnimatorPlaybackController createAnimationToNewWorkspace(
LauncherState state, long duration, @AnimationFlags int animComponents) {
- return createAnimationToNewWorkspace(state, new AnimatorSetBuilder(), duration, null,
- animComponents);
+ StateAnimationConfig config = new StateAnimationConfig();
+ config.duration = duration;
+ config.animFlags = animComponents;
+ return createAnimationToNewWorkspace(state, config);
}
public AnimatorPlaybackController createAnimationToNewWorkspace(LauncherState state,
- AnimatorSetBuilder builder, long duration, Runnable onCancelRunnable,
- @AnimationFlags int animComponents) {
+ StateAnimationConfig config) {
mConfig.reset();
- mConfig.userControlled = true;
- mConfig.mAnimFlags = animComponents;
- mConfig.duration = duration;
- mConfig.playbackController = AnimatorPlaybackController.wrap(
- createAnimationToNewWorkspaceInternal(state, builder, null), duration)
- .setOnCancelRunnable(onCancelRunnable);
+ config.copyTo(mConfig);
+ mConfig.playbackController = createAnimationToNewWorkspaceInternal(state)
+ .createPlaybackController();
return mConfig.playbackController;
}
- protected AnimatorSet createAnimationToNewWorkspaceInternal(final LauncherState state,
- AnimatorSetBuilder builder, final Runnable onCompleteRunnable) {
-
+ private PendingAnimation createAnimationToNewWorkspaceInternal(final LauncherState state) {
+ PendingAnimation builder = new PendingAnimation(mConfig.duration);
for (StateHandler handler : getStateHandlers()) {
- handler.setStateWithAnimation(state, builder, mConfig);
+ handler.setStateWithAnimation(state, mConfig, builder);
}
-
- final AnimatorSet animation = builder.build();
- animation.addListener(new AnimationSuccessListener() {
+ builder.getAnim().addListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
@@ -397,15 +346,11 @@
@Override
public void onAnimationSuccess(Animator animator) {
- // Run any queued runnables
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
onStateTransitionEnd(state);
}
});
- mConfig.setAnimation(animation, state);
- return mConfig.mCurrentAnimation;
+ mConfig.setAnimation(builder.getAnim(), state);
+ return builder;
}
private void onStateTransitionStart(LauncherState state) {
@@ -452,7 +397,7 @@
}
public void moveToRestState() {
- if (mConfig.mCurrentAnimation != null && mConfig.userControlled) {
+ if (mConfig.currentAnimation != null && mConfig.userControlled) {
// The user is doing something. Lets not mess it up
return;
}
@@ -500,12 +445,12 @@
&& mConfig.playbackController.getTarget() == childAnim) {
clearCurrentAnimation();
break;
- } else if (mConfig.mCurrentAnimation == childAnim) {
+ } else if (mConfig.currentAnimation == childAnim) {
clearCurrentAnimation();
break;
}
}
- boolean reapplyNeeded = mConfig.mCurrentAnimation != null;
+ boolean reapplyNeeded = mConfig.currentAnimation != null;
cancelAnimation();
if (reapplyNeeded) {
reapplyState();
@@ -557,9 +502,9 @@
}
private void clearCurrentAnimation() {
- if (mConfig.mCurrentAnimation != null) {
- mConfig.mCurrentAnimation.removeListener(mConfig);
- mConfig.mCurrentAnimation = null;
+ if (mConfig.currentAnimation != null) {
+ mConfig.currentAnimation.removeListener(mConfig);
+ mConfig.currentAnimation = null;
}
mConfig.playbackController = null;
}
@@ -574,54 +519,42 @@
@Override
public void run() {
- if (mConfig.mCurrentAnimation != mAnim) {
+ if (mConfig.currentAnimation != mAnim) {
return;
}
mAnim.start();
}
}
- public static class AnimationConfig extends AnimatorListenerAdapter {
- public long duration;
- public boolean userControlled;
- public AnimatorPlaybackController playbackController;
- private @AnimationFlags int mAnimFlags = ANIM_ALL_COMPONENTS;
- private PropertySetter mPropertySetter;
+ private static class AnimationState extends StateAnimationConfig implements AnimatorListener {
- private AnimatorSet mCurrentAnimation;
- private LauncherState mTargetState;
+ private static final StateAnimationConfig DEFAULT = new StateAnimationConfig();
+
+ public AnimatorPlaybackController playbackController;
+ public AnimatorSet currentAnimation;
+ public LauncherState targetState;
+
// Id to keep track of config changes, to tie an animation with the corresponding request
- private int mChangeId = 0;
+ public int changeId = 0;
/**
* Cancels the current animation and resets config variables.
*/
public void reset() {
- duration = 0;
- userControlled = false;
- mAnimFlags = ANIM_ALL_COMPONENTS;
- mPropertySetter = null;
- mTargetState = null;
+ DEFAULT.copyTo(this);
+ targetState = null;
if (playbackController != null) {
playbackController.getAnimationPlayer().cancel();
playbackController.dispatchOnCancel();
- } else if (mCurrentAnimation != null) {
- mCurrentAnimation.setDuration(0);
- mCurrentAnimation.cancel();
+ } else if (currentAnimation != null) {
+ currentAnimation.setDuration(0);
+ currentAnimation.cancel();
}
- mCurrentAnimation = null;
+ currentAnimation = null;
playbackController = null;
- mChangeId ++;
- }
-
- public PropertySetter getPropertySetter(AnimatorSetBuilder builder) {
- if (mPropertySetter == null) {
- mPropertySetter = duration == 0 ? NO_ANIM_PROPERTY_SETTER
- : new AnimatedPropertySetter(duration, builder);
- }
- return mPropertySetter;
+ changeId++;
}
@Override
@@ -629,51 +562,25 @@
if (playbackController != null && playbackController.getTarget() == animation) {
playbackController = null;
}
- if (mCurrentAnimation == animation) {
- mCurrentAnimation = null;
+ if (currentAnimation == animation) {
+ currentAnimation = null;
}
}
public void setAnimation(AnimatorSet animation, LauncherState targetState) {
- mCurrentAnimation = animation;
- mTargetState = targetState;
- mCurrentAnimation.addListener(this);
+ currentAnimation = animation;
+ this.targetState = targetState;
+ currentAnimation.addListener(this);
}
- /**
- * @return Whether Overview is scaling as part of this animation. If this is the only
- * component (i.e. NON_ATOMIC_COMPONENT isn't included), then this scaling is happening
- * atomically, rather than being part of a normal state animation. StateHandlers can use
- * this to designate part of their animation that should scale with Overview.
- */
- public boolean playAtomicOverviewScaleComponent() {
- return hasAnimationFlag(PLAY_ATOMIC_OVERVIEW_SCALE);
- }
+ @Override
+ public void onAnimationStart(Animator animator) { }
- /**
- * @return Whether this animation will play atomically at the same time as a different,
- * user-controlled state transition. StateHandlers, which contribute to both animations, can
- * use this to avoid animating the same properties in both animations, since they'd conflict
- * with one another.
- */
- public boolean onlyPlayAtomicComponent() {
- return getAnimComponents() == PLAY_ATOMIC_OVERVIEW_SCALE
- || getAnimComponents() == PLAY_ATOMIC_OVERVIEW_PEEK;
- }
+ @Override
+ public void onAnimationCancel(Animator animator) { }
- /**
- * Returns true if the config and any of the provided component flags
- */
- public boolean hasAnimationFlag(@AnimationFlags int a) {
- return (mAnimFlags & a) != 0;
- }
-
- /**
- * @return Only the flags that determine which animation components to play.
- */
- public @AnimationFlags int getAnimComponents() {
- return mAnimFlags & ANIM_ALL_COMPONENTS;
- }
+ @Override
+ public void onAnimationRepeat(Animator animator) { }
}
public interface StateHandler {
@@ -686,8 +593,8 @@
/**
* Sets the UI to {@param state} by animating any changes.
*/
- void setStateWithAnimation(LauncherState toState,
- AnimatorSetBuilder builder, AnimationConfig config);
+ void setStateWithAnimation(
+ LauncherState toState, StateAnimationConfig config, PendingAnimation animation);
}
public interface StateListener {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fc1a074..ead6018 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -60,11 +60,10 @@
import android.widget.Toast;
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.FolderDotInfo;
import com.android.launcher3.dragndrop.DragController;
@@ -83,6 +82,7 @@
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.WorkspaceTouchListener;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -1383,10 +1383,10 @@
* Sets the current workspace {@link LauncherState}, then animates the UI
*/
@Override
- public void setStateWithAnimation(LauncherState toState,
- AnimatorSetBuilder builder, AnimationConfig config) {
+ public void setStateWithAnimation(
+ LauncherState toState, StateAnimationConfig config, PendingAnimation animation) {
StateTransitionListener listener = new StateTransitionListener(toState);
- mStateTransitionAnimation.setStateWithAnimation(toState, builder, config);
+ mStateTransitionAnimation.setStateWithAnimation(toState, config, animation);
// Invalidate the pages now, so that we have the visible pages before the
// animation is started
@@ -1399,7 +1399,7 @@
stepAnimator.addUpdateListener(listener);
stepAnimator.setDuration(config.duration);
stepAnimator.addListener(listener);
- builder.play(stepAnimator);
+ animation.add(stepAnimator);
}
public WorkspaceStateTransitionAnimation getStateTransitionAnimation() {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 6653426..c521c34 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -22,27 +22,27 @@
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SCRIM_PROGRESS;
import static com.android.launcher3.graphics.WorkspaceAndHotseatScrim.SYSUI_PROGRESS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import android.view.View;
import android.view.animation.Interpolator;
import com.android.launcher3.LauncherState.PageAlphaProvider;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
+import com.android.launcher3.states.StateAnimationConfig;
/**
* Manages the animations between each of the workspace states.
@@ -60,13 +60,15 @@
}
public void setState(LauncherState toState) {
- setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(),
- new AnimationConfig());
+ setWorkspaceProperty(toState, NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig());
}
- public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
- AnimationConfig config) {
- setWorkspaceProperty(toState, config.getPropertySetter(builder), builder, config);
+ /**
+ * @see com.android.launcher3.LauncherStateManager.StateHandler#setStateWithAnimation
+ */
+ public void setStateWithAnimation(
+ LauncherState toState, StateAnimationConfig config, PendingAnimation animation) {
+ setWorkspaceProperty(toState, animation, config);
}
public float getFinalScale() {
@@ -77,7 +79,7 @@
* Starts a transition animation for the workspace.
*/
private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
- AnimatorSetBuilder builder, AnimationConfig config) {
+ StateAnimationConfig config) {
ScaleAndTranslation scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
ScaleAndTranslation hotseatScaleAndTranslation = state.getHotseatScaleAndTranslation(
mLauncher);
@@ -87,11 +89,11 @@
final int childCount = mWorkspace.getChildCount();
for (int i = 0; i < childCount; i++) {
applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
- propertySetter, builder, config);
+ propertySetter, config);
}
int elements = state.getVisibleElements(mLauncher);
- Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
+ Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
pageAlphaProvider.interpolator);
boolean playAtomicComponent = config.playAtomicOverviewScaleComponent();
Hotseat hotseat = mWorkspace.getHotseat();
@@ -99,7 +101,7 @@
AllAppsContainerView qsbScaleView = mLauncher.getAppsView();
View qsbView = qsbScaleView.getSearchView();
if (playAtomicComponent) {
- Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
+ Interpolator scaleInterpolator = config.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
if (!hotseat.getRotationMode().isTransposed) {
@@ -107,7 +109,7 @@
setPivotToScaleWithWorkspace(qsbScaleView);
}
float hotseatScale = hotseatScaleAndTranslation.scale;
- Interpolator hotseatScaleInterpolator = builder.getInterpolator(ANIM_HOTSEAT_SCALE,
+ Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
scaleInterpolator);
propertySetter.setFloat(hotseat, SCALE_PROPERTY, hotseatScale,
hotseatScaleInterpolator);
@@ -127,13 +129,13 @@
Interpolator translationInterpolator = !playAtomicComponent
? LINEAR
- : builder.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
+ : config.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_X,
scaleAndTranslation.translationX, translationInterpolator);
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_Y,
scaleAndTranslation.translationY, translationInterpolator);
- Interpolator hotseatTranslationInterpolator = builder.getInterpolator(
+ Interpolator hotseatTranslationInterpolator = config.getInterpolator(
ANIM_HOTSEAT_TRANSLATE, translationInterpolator);
propertySetter.setFloat(hotseat, VIEW_TRANSLATE_Y,
hotseatScaleAndTranslation.translationY, hotseatTranslationInterpolator);
@@ -166,12 +168,12 @@
public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
applyChildState(state, cl, childIndex, state.getWorkspacePageAlphaProvider(mLauncher),
- NO_ANIM_PROPERTY_SETTER, new AnimatorSetBuilder(), new AnimationConfig());
+ NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig());
}
private void applyChildState(LauncherState state, CellLayout cl, int childIndex,
PageAlphaProvider pageAlphaProvider, PropertySetter propertySetter,
- AnimatorSetBuilder builder, AnimationConfig config) {
+ StateAnimationConfig config) {
float pageAlpha = pageAlphaProvider.getPageAlpha(childIndex);
int drawableAlpha = Math.round(pageAlpha * (state.hasWorkspacePageBackground ? 255 : 0));
@@ -181,7 +183,7 @@
DRAWABLE_ALPHA, drawableAlpha, ZOOM_OUT);
}
if (config.playAtomicOverviewScaleComponent()) {
- Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
+ Interpolator fadeInterpolator = config.getInterpolator(ANIM_WORKSPACE_FADE,
pageAlphaProvider.interpolator);
propertySetter.setFloat(cl.getShortcutsAndWidgets(), VIEW_ALPHA,
pageAlpha, fadeInterpolator);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 744f4eb..7600f52 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -5,13 +5,13 @@
import static com.android.launcher3.LauncherState.APPS_VIEW_ITEM_MASK;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.util.SystemUiController.UI_STATE_ALL_APPS;
import android.animation.Animator;
@@ -24,12 +24,12 @@
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ScrimView;
@@ -112,7 +112,7 @@
* @param progress value between 0 and 1, 0 shows all apps and 1 shows workspace
*
* @see #setState(LauncherState)
- * @see #setStateWithAnimation(LauncherState, AnimatorSetBuilder, AnimationConfig)
+ * @see #setStateWithAnimation(LauncherState, StateAnimationConfig, PendingAnimation)
*/
public void setProgress(float progress) {
mProgress = progress;
@@ -143,7 +143,7 @@
@Override
public void setState(LauncherState state) {
setProgress(state.getVerticalProgress(mLauncher));
- setAlphas(state, null, new AnimatorSetBuilder());
+ setAlphas(state, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
onProgressAnimationEnd();
}
@@ -153,7 +153,7 @@
*/
@Override
public void setStateWithAnimation(LauncherState toState,
- AnimatorSetBuilder builder, AnimationConfig config) {
+ StateAnimationConfig config, PendingAnimation builder) {
float targetProgress = toState.getVerticalProgress(mLauncher);
if (Float.compare(mProgress, targetProgress) == 0) {
setAlphas(toState, config, builder);
@@ -168,14 +168,14 @@
}
Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
- ? builder.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
+ ? config.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
: FAST_OUT_SLOW_IN;
+
Animator anim = createSpringAnimation(mProgress, targetProgress);
anim.setDuration(config.duration);
- anim.setInterpolator(builder.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
+ anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
anim.addListener(getProgressAnimatorListener());
-
- builder.play(anim);
+ builder.add(anim);
setAlphas(toState, config, builder);
}
@@ -184,21 +184,18 @@
return ObjectAnimator.ofFloat(this, ALL_APPS_PROGRESS, progressValues);
}
- private void setAlphas(LauncherState toState, AnimationConfig config,
- AnimatorSetBuilder builder) {
- setAlphas(toState.getVisibleElements(mLauncher), config, builder);
- }
-
- public void setAlphas(int visibleElements, AnimationConfig config, AnimatorSetBuilder builder) {
- PropertySetter setter = config == null ? NO_ANIM_PROPERTY_SETTER
- : config.getPropertySetter(builder);
+ /**
+ * Updates the property for the provided state
+ */
+ public void setAlphas(LauncherState state, StateAnimationConfig config, PropertySetter setter) {
+ int visibleElements = state.getVisibleElements(mLauncher);
boolean hasHeaderExtra = (visibleElements & ALL_APPS_HEADER_EXTRA) != 0;
boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0;
boolean hasAnyVisibleItem = (visibleElements & APPS_VIEW_ITEM_MASK) != 0;
- Interpolator allAppsFade = builder.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
- Interpolator headerFade = builder.getInterpolator(ANIM_ALL_APPS_HEADER_FADE, allAppsFade);
+ Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
+ Interpolator headerFade = config.getInterpolator(ANIM_ALL_APPS_HEADER_FADE, allAppsFade);
setter.setViewAlpha(mAppsView.getContentView(), hasAllAppsContent ? 1 : 0, allAppsFade);
setter.setViewAlpha(mAppsView.getScrollBar(), hasAllAppsContent ? 1 : 0, allAppsFade);
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasAllAppsContent,
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 1fc21fd..f12789a 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -64,13 +64,6 @@
return new AnimatorPlaybackController(anim, duration, childAnims);
}
- public static AnimatorPlaybackController wrap(PendingAnimation anim, long duration) {
- /**
- * TODO: use {@link AnimatorSet#setCurrentPlayTime(long)} once b/68382377 is fixed.
- */
- return new AnimatorPlaybackController(anim.anim, duration, anim.animHolders);
- }
-
private static final FloatProperty<ValueAnimator> CURRENT_PLAY_TIME =
new FloatProperty<ValueAnimator>("current-play-time") {
@Override
@@ -84,6 +77,9 @@
}
};
+ // Progress factor after which an animation is considered almost completed.
+ private static final float ANIMATION_COMPLETE_THRESHOLD = 0.95f;
+
private final ValueAnimator mAnimationPlayer;
private final long mDuration;
@@ -96,8 +92,8 @@
protected boolean mTargetCancelled = false;
protected Runnable mOnCancelRunnable;
- private AnimatorPlaybackController(
- AnimatorSet anim, long duration, ArrayList<Holder> childAnims) {
+ /** package private */
+ AnimatorPlaybackController(AnimatorSet anim, long duration, ArrayList<Holder> childAnims) {
mAnim = anim;
mDuration = duration;
@@ -217,6 +213,16 @@
}
/**
+ * Tries to finish the running animation if it is close to completion.
+ */
+ public void forceFinishIfCloseToEnd() {
+ if (mAnimationPlayer.isRunning()
+ && mAnimationPlayer.getAnimatedFraction() > ANIMATION_COMPLETE_THRESHOLD) {
+ mAnimationPlayer.end();
+ }
+ }
+
+ /**
* Pauses the currently playing animation.
*/
public void pause() {
diff --git a/src/com/android/launcher3/anim/AnimatorSetBuilder.java b/src/com/android/launcher3/anim/AnimatorSetBuilder.java
deleted file mode 100644
index d814b19..0000000
--- a/src/com/android/launcher3/anim/AnimatorSetBuilder.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 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.anim;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.util.SparseArray;
-import android.view.animation.Interpolator;
-
-import java.util.ArrayList;
-
-/**
- * Utility class for building animator set
- */
-public class AnimatorSetBuilder {
-
- public static final int ANIM_VERTICAL_PROGRESS = 0;
- public static final int ANIM_WORKSPACE_SCALE = 1;
- public static final int ANIM_WORKSPACE_TRANSLATE = 2;
- public static final int ANIM_WORKSPACE_FADE = 3;
- public static final int ANIM_HOTSEAT_SCALE = 4;
- public static final int ANIM_HOTSEAT_TRANSLATE = 5;
- public static final int ANIM_OVERVIEW_SCALE = 6;
- public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
- public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
- public static final int ANIM_OVERVIEW_FADE = 9;
- public static final int ANIM_ALL_APPS_FADE = 10;
- public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
- public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
-
- protected final ArrayList<Animator> mAnims = new ArrayList<>();
-
- private final SparseArray<Interpolator> mInterpolators = new SparseArray<>();
-
- public void play(Animator anim) {
- mAnims.add(anim);
- }
-
- public AnimatorSet build() {
- AnimatorSet anim = new AnimatorSet();
- anim.playTogether(mAnims);
- return anim;
- }
-
- public Interpolator getInterpolator(int animId, Interpolator fallback) {
- return mInterpolators.get(animId, fallback);
- }
-
- public void setInterpolator(int animId, Interpolator interpolator) {
- mInterpolators.put(animId, interpolator);
- }
-}
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 562d160..a95a5e1 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -19,9 +19,12 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
-import android.annotation.TargetApi;
-import android.os.Build;
+import android.animation.ValueAnimator;
+import android.util.FloatProperty;
+import android.util.IntProperty;
+import android.view.View;
import com.android.launcher3.anim.AnimatorPlaybackController.Holder;
@@ -37,22 +40,28 @@
*
* TODO: Find a better name
*/
-@TargetApi(Build.VERSION_CODES.O)
-public class PendingAnimation {
+public class PendingAnimation implements PropertySetter {
private final ArrayList<Consumer<EndState>> mEndListeners = new ArrayList<>();
- /** package private **/
- final AnimatorSet anim = new AnimatorSet();
- final ArrayList<Holder> animHolders = new ArrayList<>();
+ private final ArrayList<Holder> mAnimHolders = new ArrayList<>();
+ private final AnimatorSet mAnim;
+ private final long mDuration;
+
+ private ValueAnimator mProgressAnimator;
+
+ public PendingAnimation(long duration) {
+ this(duration, new AnimatorSet());
+ }
+
+ public PendingAnimation(long duration, AnimatorSet targetSet) {
+ mDuration = duration;
+ mAnim = targetSet;
+ }
/**
* Utility method to sent an interpolator on an animation and add it to the list
*/
- public void add(Animator anim, TimeInterpolator interpolator) {
- add(anim, interpolator, SpringProperty.DEFAULT);
- }
-
public void add(Animator anim, TimeInterpolator interpolator, SpringProperty springProperty) {
anim.setInterpolator(interpolator);
add(anim, springProperty);
@@ -63,8 +72,8 @@
}
public void add(Animator a, SpringProperty springProperty) {
- anim.play(a);
- addAnimationHoldersRecur(a, springProperty, animHolders);
+ mAnim.play(a);
+ addAnimationHoldersRecur(a, springProperty, mAnimHolders);
}
public void finish(boolean isSuccess, int logAction) {
@@ -74,6 +83,67 @@
mEndListeners.clear();
}
+ @Override
+ public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
+ if (view == null || view.getAlpha() == alpha) {
+ return;
+ }
+ ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
+ anim.addListener(new AlphaUpdateListener(view));
+ anim.setDuration(mDuration).setInterpolator(interpolator);
+ add(anim);
+ }
+
+ @Override
+ public <T> void setFloat(T target, FloatProperty<T> property, float value,
+ TimeInterpolator interpolator) {
+ if (property.get(target) == value) {
+ return;
+ }
+ Animator anim = ObjectAnimator.ofFloat(target, property, value);
+ anim.setDuration(mDuration).setInterpolator(interpolator);
+ add(anim);
+ }
+
+ @Override
+ public <T> void setInt(T target, IntProperty<T> property, int value,
+ TimeInterpolator interpolator) {
+ if (property.get(target) == value) {
+ return;
+ }
+ Animator anim = ObjectAnimator.ofInt(target, property, value);
+ anim.setDuration(mDuration).setInterpolator(interpolator);
+ add(anim);
+ }
+
+ /**
+ * Adds a callback to be run on every frame of the animation
+ */
+ public void addOnFrameCallback(Runnable runnable) {
+ if (mProgressAnimator == null) {
+ mProgressAnimator = ValueAnimator.ofFloat(0, 1).setDuration(mDuration);
+ add(mProgressAnimator);
+ }
+
+ mProgressAnimator.addUpdateListener(anim -> runnable.run());
+ }
+
+ public AnimatorSet getAnim() {
+ return mAnim;
+ }
+
+ /**
+ * Creates a controller for this animation
+ */
+ public AnimatorPlaybackController createPlaybackController() {
+ return new AnimatorPlaybackController(mAnim, mDuration, mAnimHolders);
+ }
+
+ /**
+ * Add a listener of receiving the end state.
+ * Note that the listeners are called as a result of calling {@link #finish(boolean, int)}
+ * and not automatically
+ */
public void addEndListener(Consumer<EndState> listener) {
mEndListeners.add(listener);
}
diff --git a/src/com/android/launcher3/anim/PropertySetter.java b/src/com/android/launcher3/anim/PropertySetter.java
index 0b2eb48..2ce620b 100644
--- a/src/com/android/launcher3/anim/PropertySetter.java
+++ b/src/com/android/launcher3/anim/PropertySetter.java
@@ -16,8 +16,6 @@
package com.android.launcher3.anim;
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.util.FloatProperty;
import android.util.IntProperty;
@@ -26,68 +24,35 @@
/**
* Utility class for setting a property with or without animation
*/
-public class PropertySetter {
+public interface PropertySetter {
- public static final PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter();
+ PropertySetter NO_ANIM_PROPERTY_SETTER = new PropertySetter() { };
- public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
+ /**
+ * Sets the view alpha using the provided interpolator.
+ * Unlike {@link #setFloat}, this also updates the visibility of the view as alpha changes
+ * between zero and non-zero.
+ */
+ default void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
if (view != null) {
view.setAlpha(alpha);
AlphaUpdateListener.updateVisibility(view);
}
}
- public <T> void setFloat(T target, FloatProperty<T> property, float value,
+ /**
+ * Updates the float property of the target using the provided interpolator
+ */
+ default <T> void setFloat(T target, FloatProperty<T> property, float value,
TimeInterpolator interpolator) {
property.setValue(target, value);
}
- public <T> void setInt(T target, IntProperty<T> property, int value,
+ /**
+ * Updates the int property of the target using the provided interpolator
+ */
+ default <T> void setInt(T target, IntProperty<T> property, int value,
TimeInterpolator interpolator) {
property.setValue(target, value);
}
-
- public static class AnimatedPropertySetter extends PropertySetter {
-
- private final long mDuration;
- private final AnimatorSetBuilder mStateAnimator;
-
- public AnimatedPropertySetter(long duration, AnimatorSetBuilder builder) {
- mDuration = duration;
- mStateAnimator = builder;
- }
-
- @Override
- public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
- if (view == null || view.getAlpha() == alpha) {
- return;
- }
- ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, alpha);
- anim.addListener(new AlphaUpdateListener(view));
- anim.setDuration(mDuration).setInterpolator(interpolator);
- mStateAnimator.play(anim);
- }
-
- @Override
- public <T> void setFloat(T target, FloatProperty<T> property, float value,
- TimeInterpolator interpolator) {
- if (property.get(target) == value) {
- return;
- }
- Animator anim = ObjectAnimator.ofFloat(target, property, value);
- anim.setDuration(mDuration).setInterpolator(interpolator);
- mStateAnimator.play(anim);
- }
-
- @Override
- public <T> void setInt(T target, IntProperty<T> property, int value,
- TimeInterpolator interpolator) {
- if (property.get(target) == value) {
- return;
- }
- Animator anim = ObjectAnimator.ofInt(target, property, value);
- anim.setDuration(mDuration).setInterpolator(interpolator);
- mStateAnimator.play(anim);
- }
- }
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index af769c8..0237b50 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -83,6 +83,9 @@
public static final BooleanFlag UNSTABLE_SPRINGS = getDebugFlag(
"UNSTABLE_SPRINGS", false, "Enable unstable springs for quickstep animations");
+ public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
+ "KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
+
public static final BooleanFlag ADAPTIVE_ICON_WINDOW_ANIM = getDebugFlag(
"ADAPTIVE_ICON_WINDOW_ANIM", true, "Use adaptive icons for window animations.");
@@ -103,8 +106,8 @@
"APP_SEARCH_IMPROVEMENTS", true,
"Adds localized title and keyword search and ranking");
- public static final BooleanFlag ENABLE_PREDICTION_DISMISS = new DeviceFlag(
- "ENABLE_PREDICTION_DISMISS", true, "Allow option to dimiss apps from predicted list");
+ public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
+ "ENABLE_PREDICTION_DISMISS", false, "Allow option to dimiss apps from predicted list");
public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
"ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
@@ -117,11 +120,11 @@
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
- public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = new DeviceFlag(
+ public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = getDebugFlag(
"ENABLE_HYBRID_HOTSEAT", false, "Fill gaps in hotseat with predicted apps");
- public static final BooleanFlag HOTSEAT_MIGRATE_NEW_PAGE = new DeviceFlag(
- "HOTSEAT_MIGRATE_NEW_PAGE", true,
+ public static final BooleanFlag HOTSEAT_MIGRATE_NEW_PAGE = getDebugFlag(
+ "HOTSEAT_MIGRATE_NEW_PAGE", false,
"Migrates hotseat to a new workspace page instead of same page");
public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag(
@@ -131,13 +134,18 @@
"MULTI_DB_GRID_MIRATION_ALGO", false, "Use the multi-db grid migration algorithm");
public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag(
- "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true,
- "Show launcher preview in grid picker");
+ "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true, "Show launcher preview in grid picker");
+
+ public static final BooleanFlag USE_SURFACE_VIEW_FOR_GRID_PREVIEW = getDebugFlag(
+ "USE_SURFACE_VIEW_FOR_GRID_PREVIEW", false, "Use surface view for grid preview");
public static final BooleanFlag ENABLE_OVERVIEW_ACTIONS = getDebugFlag(
"ENABLE_OVERVIEW_ACTIONS", true, "Show app actions instead of the shelf in Overview."
+ " As part of this decoupling, also distinguish swipe up from nav bar vs above it.");
+ public static final BooleanFlag ENABLE_SELECT_MODE = getDebugFlag(
+ "ENABLE_SELECT_MODE", true, "Show Select Mode button in Overview Actions");
+
public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
"ENABLE_DATABASE_RESTORE", true,
"Enable database restore when new restore session is created");
diff --git a/src/com/android/launcher3/graphics/GridOptionsProvider.java b/src/com/android/launcher3/graphics/GridOptionsProvider.java
index 71b4366..607aba9 100644
--- a/src/com/android/launcher3/graphics/GridOptionsProvider.java
+++ b/src/com/android/launcher3/graphics/GridOptionsProvider.java
@@ -1,5 +1,6 @@
package com.android.launcher3.graphics;
+import static com.android.launcher3.config.FeatureFlags.USE_SURFACE_VIEW_FOR_GRID_PREVIEW;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.ContentProvider;
@@ -19,6 +20,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.GridOption;
import com.android.launcher3.R;
+import com.android.launcher3.uioverrides.PreviewSurfaceRenderer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -62,6 +64,11 @@
private static final String KEY_PREVIEW = "preview";
private static final String MIME_TYPE_PNG = "image/png";
+ private static final String METHOD_GET_PREVIEW = "get_preview";
+ private static final String METADATA_KEY_PREVIEW_VERSION = "preview_version";
+
+
+
public static final PipeDataWriter<Future<Bitmap>> BITMAP_WRITER =
new PipeDataWriter<Future<Bitmap>>() {
@Override
@@ -98,6 +105,10 @@
.add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns
&& idp.numRows == gridOption.numRows);
}
+ Bundle metadata = new Bundle();
+ metadata.putString(METADATA_KEY_PREVIEW_VERSION,
+ USE_SURFACE_VIEW_FOR_GRID_PREVIEW.get() ? "V2" : "V1");
+ cursor.setExtras(metadata);
return cursor;
}
@@ -188,4 +199,14 @@
throw new FileNotFoundException(e.getMessage());
}
}
+
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ if (!METHOD_GET_PREVIEW.equals(method)) {
+ return null;
+ }
+
+ PreviewSurfaceRenderer.render(getContext(), extras);
+ return null;
+ }
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 02e98e8..5bc6610 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -262,6 +262,13 @@
});
}
+ /** Populate preview and render it. */
+ public View getRenderedView() {
+ MainThreadRenderer renderer = new MainThreadRenderer(mContext);
+ renderer.populate();
+ return renderer.mRootView;
+ }
+
private class MainThreadRenderer extends ContextThemeWrapper
implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 {
@@ -388,7 +395,7 @@
}
}
- private void renderScreenShot(Canvas canvas) {
+ private void populate() {
if (ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER.get()) {
boolean needsToMigrate = needsToMigrate(mContext, mIdp);
boolean success = false;
@@ -499,7 +506,10 @@
measureView(mRootView, mDp.widthPx, mDp.heightPx);
// Additional measure for views which use auto text size API
measureView(mRootView, mDp.widthPx, mDp.heightPx);
+ }
+ private void renderScreenShot(Canvas canvas) {
+ populate();
mRootView.draw(canvas);
dispatchVisibilityAggregated(mRootView, false);
}
diff --git a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
index 83349bc..2c7f891 100644
--- a/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
+++ b/src/com/android/launcher3/graphics/WorkspaceAndHotseatScrim.java
@@ -19,6 +19,7 @@
import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_USER_PRESENT;
+import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
import android.animation.ObjectAnimator;
@@ -81,6 +82,10 @@
}
};
+ /**
+ * Receiver used to get a signal that the user unlocked their device.
+ * @see KEYGUARD_ANIMATION For proper signal.
+ */
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -164,8 +169,10 @@
mSysUiAnimMultiplier = 0;
reapplySysUiAlphaNoInvalidate();
- animateToSysuiMultiplier(1, 600,
- mLauncher.getWindow().getTransitionBackgroundFadeDuration());
+ ObjectAnimator oa = createSysuiMultiplierAnim(1);
+ oa.setDuration(600);
+ oa.setStartDelay(mLauncher.getWindow().getTransitionBackgroundFadeDuration());
+ oa.start();
mAnimateScrimOnNextDraw = false;
}
@@ -178,13 +185,13 @@
}
}
- public void animateToSysuiMultiplier(float toMultiplier, long duration,
- long startDelay) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, toMultiplier);
+ /**
+ * @return an ObjectAnimator that controls the fade in/out of the sys ui scrim.
+ */
+ public ObjectAnimator createSysuiMultiplierAnim(float... values) {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, SYSUI_ANIM_MULTIPLIER, values);
anim.setAutoCancel(true);
- anim.setDuration(duration);
- anim.setStartDelay(startDelay);
- anim.start();
+ return anim;
}
public void onInsetsChanged(Rect insets) {
@@ -197,7 +204,7 @@
public void onViewAttachedToWindow(View view) {
super.onViewAttachedToWindow(view);
- if (mTopScrim != null) {
+ if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF);
filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone
mRoot.getContext().registerReceiver(mReceiver, filter);
@@ -207,7 +214,7 @@
@Override
public void onViewDetachedFromWindow(View view) {
super.onViewDetachedFromWindow(view);
- if (mTopScrim != null) {
+ if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) {
mRoot.getContext().unregisterReceiver(mReceiver);
}
}
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 3770d17..89077ee 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -143,7 +143,7 @@
fillIntentInfo(itemTarget, intent, userHandle);
}
LauncherEvent event = newLauncherEvent(action, targets);
- ItemInfo info = (ItemInfo) v.getTag();
+ ItemInfo info = v == null ? null : (ItemInfo) v.getTag();
if (info != null && Utilities.IS_DEBUG_DEVICE && FeatureFlags.ENABLE_HYBRID_HOTSEAT.get()) {
FileLog.d(TAG, "appLaunch: packageName:" + info.getTargetComponent().getPackageName()
+ ",isWorkApp:" + (info.user != null && !Process.myUserHandle().equals(
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index 3ba740d..a084600 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -936,8 +936,8 @@
boolean dbChanged = false;
if (migrateForPreview) {
- copyTable(transaction.getDb(), Favorites.TABLE_NAME, Favorites.PREVIEW_TABLE_NAME,
- context);
+ copyTable(transaction.getDb(), Favorites.TABLE_NAME, transaction.getDb(),
+ Favorites.PREVIEW_TABLE_NAME, context);
}
GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(),
@@ -950,10 +950,11 @@
HashSet<String> validPackages = getValidPackages(context);
// Hotseat.
- if (srcHotseatCount != idp.numHotseatIcons) {
- // Migrate hotseat.
- dbChanged = new GridSizeMigrationTask(context, transaction.getDb(), validPackages,
- migrateForPreview, srcHotseatCount, idp.numHotseatIcons).migrateHotseat();
+ if (srcHotseatCount != idp.numHotseatIcons
+ && new GridSizeMigrationTask(context, transaction.getDb(), validPackages,
+ migrateForPreview, srcHotseatCount,
+ idp.numHotseatIcons).migrateHotseat()) {
+ dbChanged = true;
}
// Grid size
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
index 197b29c..0bdccfa 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java
@@ -16,9 +16,46 @@
package com.android.launcher3.model;
+import static com.android.launcher3.Utilities.getPointString;
+import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+
+import android.content.ComponentName;
+import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Point;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.graphics.LauncherPreviewRenderer;
+import com.android.launcher3.pm.InstallSessionHelper;
+import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
+import com.android.launcher3.util.GridOccupancy;
+import com.android.launcher3.util.IntArray;
+import com.android.launcher3.widget.WidgetManagerHelper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* This class takes care of shrinking the workspace (by maximum of one row and one column), as a
@@ -26,14 +63,63 @@
*/
public class GridSizeMigrationTaskV2 {
- private GridSizeMigrationTaskV2(Context context) {
+ public static final String KEY_MIGRATION_SRC_WORKSPACE_SIZE = "migration_src_workspace_size";
+ public static final String KEY_MIGRATION_SRC_HOTSEAT_COUNT = "migration_src_hotseat_count";
+ private static final String TAG = "GridSizeMigrationTaskV2";
+ private static final boolean DEBUG = true;
+
+ private final Context mContext;
+ private final SQLiteDatabase mDb;
+ private final DbReader mSrcReader;
+ private final DbReader mDestReader;
+
+ private final List<DbEntry> mHotseatItems;
+ private final List<DbEntry> mWorkspaceItems;
+
+ private final List<DbEntry> mHotseatDiff;
+ private final List<DbEntry> mWorkspaceDiff;
+
+ private final int mDestHotseatSize;
+ private final int mTrgX, mTrgY;
+
+ @VisibleForTesting
+ protected GridSizeMigrationTaskV2(Context context, SQLiteDatabase db, DbReader srcReader,
+ DbReader destReader, int destHotseatSize, Point targetSize) {
+ mContext = context;
+ mDb = db;
+ mSrcReader = srcReader;
+ mDestReader = destReader;
+
+ mHotseatItems = destReader.loadHotseatEntries();
+ mWorkspaceItems = destReader.loadAllWorkspaceEntries();
+
+ mHotseatDiff = calcDiff(mSrcReader.loadHotseatEntries(), mHotseatItems);
+ mWorkspaceDiff = calcDiff(mSrcReader.loadAllWorkspaceEntries(), mWorkspaceItems);
+ mDestHotseatSize = destHotseatSize;
+
+ mTrgX = targetSize.x;
+ mTrgY = targetSize.y;
+ }
+
+ /**
+ * Check given a new IDP, if migration is necessary.
+ */
+ public static boolean needsToMigrate(Context context, InvariantDeviceProfile idp) {
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ String gridSizeString = getPointString(idp.numColumns, idp.numRows);
+
+ return !gridSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, ""))
+ || idp.numHotseatIcons != prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT,
+ idp.numHotseatIcons);
}
/** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */
public static boolean migrateGridIfNeeded(Context context) {
- // To be implemented.
- return true;
+ if (context instanceof LauncherPreviewRenderer.PreviewContext) {
+ return true;
+ }
+ return migrateGridIfNeeded(context, null);
}
/**
@@ -43,7 +129,608 @@
* @return false if the migration failed.
*/
public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
- // To be implemented.
+ boolean migrateForPreview = idp != null;
+ if (!migrateForPreview) {
+ idp = LauncherAppState.getIDP(context);
+ }
+
+ if (!needsToMigrate(context, idp)) {
+ return true;
+ }
+
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ String gridSizeString = getPointString(idp.numColumns, idp.numRows);
+
+ if (gridSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, ""))
+ && idp.numHotseatIcons == prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT,
+ idp.numHotseatIcons)) {
+ // Skip if workspace and hotseat sizes have not changed.
+ return true;
+ }
+
+ HashSet<String> validPackages = getValidPackages(context);
+ int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons);
+
+ if (!LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER).getBoolean(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+ return false;
+ }
+
+ long migrationStartTime = System.currentTimeMillis();
+ try (SQLiteTransaction t = (SQLiteTransaction) LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+
+ DbReader srcReader = new DbReader(t.getDb(), LauncherSettings.Favorites.TMP_TABLE,
+ context, validPackages, srcHotseatCount);
+ DbReader destReader = new DbReader(t.getDb(), LauncherSettings.Favorites.TABLE_NAME,
+ context, validPackages, idp.numHotseatIcons);
+
+ Point targetSize = new Point(idp.numColumns, idp.numRows);
+ GridSizeMigrationTaskV2 task = new GridSizeMigrationTaskV2(context, t.getDb(),
+ srcReader, destReader, idp.numHotseatIcons, targetSize);
+ task.migrate();
+
+ dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
+
+ t.commit();
+ return true;
+ } catch (Exception e) {
+ Log.e(TAG, "Error during grid migration", e);
+
+ return false;
+ } finally {
+ Log.v(TAG, "Workspace migration completed in "
+ + (System.currentTimeMillis() - migrationStartTime));
+
+ // Save current configuration, so that the migration does not run again.
+ prefs.edit()
+ .putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString)
+ .putInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons)
+ .apply();
+ }
+ }
+
+ @VisibleForTesting
+ protected boolean migrate() {
+ if (mHotseatDiff.isEmpty() && mWorkspaceDiff.isEmpty()) {
+ return false;
+ }
+
+ // Migrate hotseat
+ HotseatPlacementSolution hotseatSolution = new HotseatPlacementSolution(mDb, mSrcReader,
+ mContext, mDestHotseatSize, mHotseatItems, mHotseatDiff);
+ hotseatSolution.find();
+
+ // Sort the items by the reading order.
+ Collections.sort(mWorkspaceDiff);
+
+ // Migrate workspace.
+ for (int screenId = 0; screenId <= mDestReader.mLastScreenId; screenId++) {
+ if (DEBUG) {
+ Log.d(TAG, "Migrating " + screenId);
+ }
+ List<DbEntry> entries = mDestReader.loadWorkspaceEntries(screenId);
+ GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
+ mContext, entries, screenId, mTrgX, mTrgY, mWorkspaceDiff);
+ workspaceSolution.find();
+ if (mWorkspaceDiff.isEmpty()) {
+ break;
+ }
+ }
+
+ int screenId = mDestReader.mLastScreenId + 1;
+ while (!mWorkspaceDiff.isEmpty()) {
+ GridPlacementSolution workspaceSolution = new GridPlacementSolution(mDb, mSrcReader,
+ mContext, new ArrayList<>(), screenId, mTrgX, mTrgY, mWorkspaceDiff);
+ workspaceSolution.find();
+ screenId++;
+ }
return true;
}
+
+ /** Return what's in the src but not in the dest */
+ private static List<DbEntry> calcDiff(List<DbEntry> src, List<DbEntry> dest) {
+ Set<String> destSet = dest.parallelStream().map(DbEntry::getIntentStr).collect(
+ Collectors.toSet());
+ List<DbEntry> diff = new ArrayList<>();
+ for (DbEntry entry : src) {
+ if (!destSet.contains(entry.mIntent)) {
+ diff.add(entry);
+ }
+ }
+ return diff;
+ }
+
+ private static void insertEntryInDb(SQLiteDatabase db, Context context,
+ ArrayList<DbEntry> entriesFromSrcDb, DbEntry entry) {
+ int id = -1;
+ switch (entry.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
+ for (DbEntry e : entriesFromSrcDb) {
+ if (TextUtils.equals(e.mIntent, entry.mIntent)) {
+ id = e.id;
+ }
+ }
+
+ break;
+ }
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
+ for (DbEntry e : entriesFromSrcDb) {
+ if (e.mFolderItems.size() == entry.mFolderItems.size()
+ && e.mFolderItems.containsAll(entry.mFolderItems)) {
+ id = e.id;
+ }
+ }
+ break;
+ }
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: {
+ for (DbEntry e : entriesFromSrcDb) {
+ if (TextUtils.equals(e.mProvider, entry.mProvider)) {
+ id = e.id;
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ return;
+ }
+
+ Cursor c = db.query(LauncherSettings.Favorites.TMP_TABLE, null,
+ LauncherSettings.Favorites._ID + " = '" + id + "'", null, null, null, null);
+
+ while (c.moveToNext()) {
+ ContentValues values = new ContentValues();
+ DatabaseUtils.cursorRowToContentValues(c, values);
+ entry.updateContentValues(values);
+ values.put(LauncherSettings.Favorites._ID,
+ LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt(
+ LauncherSettings.Settings.EXTRA_VALUE));
+ db.insert(LauncherSettings.Favorites.TABLE_NAME, null, values);
+ }
+ c.close();
+ }
+
+ private static void removeEntryFromDb(SQLiteDatabase db, IntArray entryId) {
+ db.delete(LauncherSettings.Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
+ LauncherSettings.Favorites._ID, entryId), null);
+ }
+
+ private static HashSet<String> getValidPackages(Context context) {
+ // Initialize list of valid packages. This contain all the packages which are already on
+ // the device and packages which are being installed. Any item which doesn't belong to
+ // this set is removed.
+ // Since the loader removes such items anyway, removing these items here doesn't cause
+ // any extra data loss and gives us more free space on the grid for better migration.
+ HashSet<String> validPackages = new HashSet<>();
+ for (PackageInfo info : context.getPackageManager()
+ .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
+ validPackages.add(info.packageName);
+ }
+ InstallSessionHelper.INSTANCE.get(context)
+ .getActiveSessions().keySet()
+ .forEach(packageUserKey -> validPackages.add(packageUserKey.mPackageName));
+ return validPackages;
+ }
+
+ protected static class GridPlacementSolution {
+
+ private final SQLiteDatabase mDb;
+ private final DbReader mSrcReader;
+ private final Context mContext;
+ private final GridOccupancy mOccupied;
+ private final int mScreenId;
+ private final int mTrgX;
+ private final int mTrgY;
+ private final List<DbEntry> mItemsToPlace;
+
+ private int mNextStartX;
+ private int mNextStartY;
+
+ GridPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context,
+ List<DbEntry> placedWorkspaceItems, int screenId, int trgX,
+ int trgY, List<DbEntry> itemsToPlace) {
+ mDb = db;
+ mSrcReader = srcReader;
+ mContext = context;
+ mOccupied = new GridOccupancy(trgX, trgY);
+ mScreenId = screenId;
+ mTrgX = trgX;
+ mTrgY = trgY;
+ mNextStartX = 0;
+ mNextStartY = mTrgY - 1;
+ for (DbEntry entry : placedWorkspaceItems) {
+ mOccupied.markCells(entry, true);
+ }
+ mItemsToPlace = itemsToPlace;
+ }
+
+ public void find() {
+ Iterator<DbEntry> iterator = mItemsToPlace.iterator();
+ while (iterator.hasNext()) {
+ final DbEntry entry = iterator.next();
+ if (entry.minSpanX > mTrgX || entry.minSpanY > mTrgY) {
+ iterator.remove();
+ continue;
+ }
+ if (findPlacement(entry)) {
+ insertEntryInDb(mDb, mContext, mSrcReader.mWorkspaceEntries, entry);
+ iterator.remove();
+ }
+ }
+ }
+
+ private boolean findPlacement(DbEntry entry) {
+ for (int y = mNextStartY; y >= 0; y--) {
+ for (int x = mNextStartX; x < mTrgX; x++) {
+ boolean fits = mOccupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
+ boolean minFits = mOccupied.isRegionVacant(x, y, entry.minSpanX,
+ entry.minSpanY);
+ if (minFits) {
+ entry.spanX = entry.minSpanX;
+ entry.spanY = entry.minSpanY;
+ }
+ if (fits || minFits) {
+ entry.screenId = mScreenId;
+ entry.cellX = x;
+ entry.cellY = y;
+ mOccupied.markCells(entry, true);
+ mNextStartX = x + entry.spanX;
+ mNextStartY = y;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ protected static class HotseatPlacementSolution {
+
+ private final SQLiteDatabase mDb;
+ private final DbReader mSrcReader;
+ private final Context mContext;
+ private final HotseatOccupancy mOccupied;
+ private final List<DbEntry> mItemsToPlace;
+
+ HotseatPlacementSolution(SQLiteDatabase db, DbReader srcReader, Context context,
+ int hotseatSize, List<DbEntry> placedHotseatItems, List<DbEntry> itemsToPlace) {
+ mDb = db;
+ mSrcReader = srcReader;
+ mContext = context;
+ mOccupied = new HotseatOccupancy(hotseatSize);
+ for (DbEntry entry : placedHotseatItems) {
+ mOccupied.markCells(entry, true);
+ }
+ mItemsToPlace = itemsToPlace;
+ }
+
+ public void find() {
+ for (int i = 0; i < mOccupied.mCells.length; i++) {
+ if (!mOccupied.mCells[i] && !mItemsToPlace.isEmpty()) {
+ DbEntry entry = mItemsToPlace.remove(0);
+ entry.screenId = i;
+ // These values does not affect the item position, but we should set them
+ // to something other than -1.
+ entry.cellX = i;
+ entry.cellY = 0;
+ insertEntryInDb(mDb, mContext, mSrcReader.mHotseatEntries, entry);
+ mOccupied.markCells(entry, true);
+ }
+ }
+ }
+
+ private class HotseatOccupancy {
+
+ private final boolean[] mCells;
+
+ private HotseatOccupancy(int hotseatSize) {
+ mCells = new boolean[hotseatSize];
+ }
+
+ private void markCells(ItemInfo item, boolean value) {
+ mCells[item.screenId] = value;
+ }
+ }
+ }
+
+ protected static class DbReader {
+
+ private final SQLiteDatabase mDb;
+ private final String mTableName;
+ private final Context mContext;
+ private final HashSet<String> mValidPackages;
+ private final int mHotseatSize;
+ private int mLastScreenId = -1;
+
+ private final ArrayList<DbEntry> mHotseatEntries = new ArrayList<>();
+ private final ArrayList<DbEntry> mWorkspaceEntries = new ArrayList<>();
+
+ DbReader(SQLiteDatabase db, String tableName, Context context,
+ HashSet<String> validPackages, int hotseatSize) {
+ mDb = db;
+ mTableName = tableName;
+ mContext = context;
+ mValidPackages = validPackages;
+ mHotseatSize = hotseatSize;
+ }
+
+ protected ArrayList<DbEntry> loadHotseatEntries() {
+ Cursor c = queryWorkspace(
+ new String[]{
+ LauncherSettings.Favorites._ID, // 0
+ LauncherSettings.Favorites.ITEM_TYPE, // 1
+ LauncherSettings.Favorites.INTENT, // 2
+ LauncherSettings.Favorites.SCREEN}, // 3
+ LauncherSettings.Favorites.CONTAINER + " = "
+ + LauncherSettings.Favorites.CONTAINER_HOTSEAT);
+
+ final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+ final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int indexIntent = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+
+ IntArray entriesToRemove = new IntArray();
+ while (c.moveToNext()) {
+ DbEntry entry = new DbEntry();
+ entry.id = c.getInt(indexId);
+ entry.itemType = c.getInt(indexItemType);
+ entry.screenId = c.getInt(indexScreen);
+
+ if (entry.screenId >= mHotseatSize) {
+ entriesToRemove.add(entry.id);
+ continue;
+ }
+
+ try {
+ // calculate weight
+ switch (entry.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
+ entry.mIntent = c.getString(indexIntent);
+ verifyIntent(c.getString(indexIntent));
+ break;
+ }
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
+ int total = getFolderItemsCount(entry);
+ if (total == 0) {
+ throw new Exception("Folder is empty");
+ }
+ break;
+ }
+ default:
+ throw new Exception("Invalid item type");
+ }
+ } catch (Exception e) {
+ if (DEBUG) {
+ Log.d(TAG, "Removing item " + entry.id, e);
+ }
+ entriesToRemove.add(entry.id);
+ continue;
+ }
+ mHotseatEntries.add(entry);
+ }
+ removeEntryFromDb(mDb, entriesToRemove);
+ c.close();
+ return mHotseatEntries;
+ }
+
+ protected ArrayList<DbEntry> loadAllWorkspaceEntries() {
+ Cursor c = queryWorkspace(
+ new String[]{
+ LauncherSettings.Favorites._ID, // 0
+ LauncherSettings.Favorites.ITEM_TYPE, // 1
+ LauncherSettings.Favorites.SCREEN, // 2
+ LauncherSettings.Favorites.CELLX, // 3
+ LauncherSettings.Favorites.CELLY, // 4
+ LauncherSettings.Favorites.SPANX, // 5
+ LauncherSettings.Favorites.SPANY, // 6
+ LauncherSettings.Favorites.INTENT, // 7
+ LauncherSettings.Favorites.APPWIDGET_PROVIDER, // 8
+ LauncherSettings.Favorites.APPWIDGET_ID}, // 9
+ LauncherSettings.Favorites.CONTAINER + " = "
+ + LauncherSettings.Favorites.CONTAINER_DESKTOP);
+ return loadWorkspaceEntries(c);
+ }
+
+ protected ArrayList<DbEntry> loadWorkspaceEntries(int screen) {
+ Cursor c = queryWorkspace(
+ new String[]{
+ LauncherSettings.Favorites._ID, // 0
+ LauncherSettings.Favorites.ITEM_TYPE, // 1
+ LauncherSettings.Favorites.SCREEN, // 2
+ LauncherSettings.Favorites.CELLX, // 3
+ LauncherSettings.Favorites.CELLY, // 4
+ LauncherSettings.Favorites.SPANX, // 5
+ LauncherSettings.Favorites.SPANY, // 6
+ LauncherSettings.Favorites.INTENT, // 7
+ LauncherSettings.Favorites.APPWIDGET_PROVIDER, // 8
+ LauncherSettings.Favorites.APPWIDGET_ID}, // 9
+ LauncherSettings.Favorites.CONTAINER + " = "
+ + LauncherSettings.Favorites.CONTAINER_DESKTOP
+ + " AND " + LauncherSettings.Favorites.SCREEN + " = " + screen);
+ return loadWorkspaceEntries(c);
+ }
+
+ private ArrayList<DbEntry> loadWorkspaceEntries(Cursor c) {
+ final int indexId = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+ final int indexItemType = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int indexScreen = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int indexCellX = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int indexCellY = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int indexSpanX = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
+ final int indexSpanY = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
+ final int indexIntent = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int indexAppWidgetProvider = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.APPWIDGET_PROVIDER);
+ final int indexAppWidgetId = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.APPWIDGET_ID);
+
+ IntArray entriesToRemove = new IntArray();
+ WidgetManagerHelper widgetManagerHelper = new WidgetManagerHelper(mContext);
+ while (c.moveToNext()) {
+ DbEntry entry = new DbEntry();
+ entry.id = c.getInt(indexId);
+ entry.itemType = c.getInt(indexItemType);
+ entry.screenId = c.getInt(indexScreen);
+ mLastScreenId = Math.max(mLastScreenId, entry.screenId);
+ entry.cellX = c.getInt(indexCellX);
+ entry.cellY = c.getInt(indexCellY);
+ entry.spanX = c.getInt(indexSpanX);
+ entry.spanY = c.getInt(indexSpanY);
+
+ try {
+ // calculate weight
+ switch (entry.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
+ entry.mIntent = c.getString(indexIntent);
+ verifyIntent(entry.mIntent);
+ break;
+ }
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: {
+ entry.mProvider = c.getString(indexAppWidgetProvider);
+ ComponentName cn = ComponentName.unflattenFromString(entry.mProvider);
+ verifyPackage(cn.getPackageName());
+
+ int widgetId = c.getInt(indexAppWidgetId);
+ LauncherAppWidgetProviderInfo pInfo =
+ widgetManagerHelper.getLauncherAppWidgetInfo(widgetId);
+ Point spans = null;
+ if (pInfo != null) {
+ spans = pInfo.getMinSpans();
+ }
+ if (spans != null) {
+ entry.minSpanX = spans.x > 0 ? spans.x : entry.spanX;
+ entry.minSpanY = spans.y > 0 ? spans.y : entry.spanY;
+ } else {
+ // Assume that the widget be resized down to 2x2
+ entry.minSpanX = entry.minSpanY = 2;
+ }
+
+ break;
+ }
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: {
+ int total = getFolderItemsCount(entry);
+ if (total == 0) {
+ throw new Exception("Folder is empty");
+ }
+ break;
+ }
+ default:
+ throw new Exception("Invalid item type");
+ }
+ } catch (Exception e) {
+ if (DEBUG) {
+ Log.d(TAG, "Removing item " + entry.id, e);
+ }
+ entriesToRemove.add(entry.id);
+ continue;
+ }
+ mWorkspaceEntries.add(entry);
+ }
+ removeEntryFromDb(mDb, entriesToRemove);
+ c.close();
+ return mWorkspaceEntries;
+ }
+
+ private int getFolderItemsCount(DbEntry entry) {
+ Cursor c = queryWorkspace(
+ new String[]{LauncherSettings.Favorites._ID, LauncherSettings.Favorites.INTENT},
+ LauncherSettings.Favorites.CONTAINER + " = " + entry.id);
+
+ int total = 0;
+ while (c.moveToNext()) {
+ try {
+ String intent = c.getString(1);
+ verifyIntent(intent);
+ total++;
+ entry.mFolderItems.add(intent);
+ } catch (Exception e) {
+ removeEntryFromDb(mDb, IntArray.wrap(c.getInt(0)));
+ }
+ }
+ c.close();
+ return total;
+ }
+
+ private Cursor queryWorkspace(String[] columns, String where) {
+ return mDb.query(mTableName, columns, where, null, null, null, null);
+ }
+
+ /** Verifies if the mIntent should be restored. */
+ private void verifyIntent(String intentStr)
+ throws Exception {
+ Intent intent = Intent.parseUri(intentStr, 0);
+ if (intent.getComponent() != null) {
+ verifyPackage(intent.getComponent().getPackageName());
+ } else if (intent.getPackage() != null) {
+ // Only verify package if the component was null.
+ verifyPackage(intent.getPackage());
+ }
+ }
+
+ /** Verifies if the package should be restored */
+ private void verifyPackage(String packageName)
+ throws Exception {
+ if (!mValidPackages.contains(packageName)) {
+ // TODO(b/151468819): Handle promise app icon restoration during grid migration.
+ throw new Exception("Package not available");
+ }
+ }
+ }
+
+ protected static class DbEntry extends ItemInfo implements Comparable<DbEntry> {
+
+ private String mIntent;
+ private String mProvider;
+ private Set<String> mFolderItems = new HashSet<>();
+
+ /** Comparator according to the reading order */
+ @Override
+ public int compareTo(DbEntry another) {
+ if (screenId != another.screenId) {
+ return Integer.compare(screenId, another.screenId);
+ }
+ if (cellY != another.cellY) {
+ return -Integer.compare(cellY, another.cellY);
+ }
+ return Integer.compare(cellX, another.cellX);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DbEntry entry = (DbEntry) o;
+ return Objects.equals(mIntent, entry.mIntent);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIntent);
+ }
+
+ public void updateContentValues(ContentValues values) {
+ values.put(LauncherSettings.Favorites.SCREEN, screenId);
+ values.put(LauncherSettings.Favorites.CELLX, cellX);
+ values.put(LauncherSettings.Favorites.CELLY, cellY);
+ values.put(LauncherSettings.Favorites.SPANX, spanX);
+ values.put(LauncherSettings.Favorites.SPANY, spanY);
+ }
+
+ public String getIntentStr() {
+ return mIntent;
+ }
+ }
}
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index f7ecc3f..dacea84 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -118,13 +118,20 @@
db.execSQL("DROP TABLE IF EXISTS " + tableName);
}
- /** Copy from table to the to table. */
- public static void copyTable(SQLiteDatabase db, String from, String to, Context context) {
+ /** Copy fromTable in fromDb to toTable in toDb. */
+ public static void copyTable(SQLiteDatabase fromDb, String fromTable, SQLiteDatabase toDb,
+ String toTable, Context context) {
long userSerial = UserCache.INSTANCE.get(context).getSerialNumberForUser(
Process.myUserHandle());
- dropTable(db, to);
- Favorites.addTableToDb(db, userSerial, false, to);
- db.execSQL("INSERT INTO " + to + " SELECT * FROM " + from);
+ dropTable(toDb, toTable);
+ Favorites.addTableToDb(toDb, userSerial, false, toTable);
+ if (fromDb != toDb) {
+ toDb.execSQL("ATTACH DATABASE '" + fromDb.getPath() + "' AS from_db");
+ toDb.execSQL(
+ "INSERT INTO " + toTable + " SELECT * FROM from_db." + fromTable);
+ } else {
+ toDb.execSQL("INSERT INTO " + toTable + " SELECT * FROM " + fromTable);
+ }
}
/**
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
new file mode 100644
index 0000000..82cde64
--- /dev/null
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -0,0 +1,155 @@
+/*
+ * 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.states;
+
+import android.view.animation.Interpolator;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Utility class for building animator set
+ */
+public class StateAnimationConfig {
+
+ // We separate the state animations into "atomic" and "non-atomic" components. The atomic
+ // components may be run atomically - that is, all at once, instead of user-controlled. However,
+ // atomic components are not restricted to this purpose; they can be user-controlled alongside
+ // non atomic components as well. Note that each gesture model has exactly one atomic component,
+ // PLAY_ATOMIC_OVERVIEW_SCALE *or* PLAY_ATOMIC_OVERVIEW_PEEK.
+ @IntDef(flag = true, value = {
+ PLAY_NON_ATOMIC,
+ PLAY_ATOMIC_OVERVIEW_SCALE,
+ PLAY_ATOMIC_OVERVIEW_PEEK,
+ SKIP_OVERVIEW,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AnimationFlags {}
+ public static final int PLAY_NON_ATOMIC = 1 << 0;
+ public static final int PLAY_ATOMIC_OVERVIEW_SCALE = 1 << 1;
+ public static final int PLAY_ATOMIC_OVERVIEW_PEEK = 1 << 2;
+ public static final int SKIP_OVERVIEW = 1 << 3;
+
+ public long duration;
+ public boolean userControlled;
+ public @AnimationFlags int animFlags = ANIM_ALL_COMPONENTS;
+
+ public static final int ANIM_ALL_COMPONENTS = PLAY_NON_ATOMIC | PLAY_ATOMIC_OVERVIEW_SCALE
+ | PLAY_ATOMIC_OVERVIEW_PEEK;
+
+ // Various types of animation state transition
+ @IntDef(value = {
+ ANIM_VERTICAL_PROGRESS,
+ ANIM_WORKSPACE_SCALE,
+ ANIM_WORKSPACE_TRANSLATE,
+ ANIM_WORKSPACE_FADE,
+ ANIM_HOTSEAT_SCALE,
+ ANIM_HOTSEAT_TRANSLATE,
+ ANIM_OVERVIEW_SCALE,
+ ANIM_OVERVIEW_TRANSLATE_X,
+ ANIM_OVERVIEW_TRANSLATE_Y,
+ ANIM_OVERVIEW_FADE,
+ ANIM_ALL_APPS_FADE,
+ ANIM_OVERVIEW_SCRIM_FADE,
+ ANIM_ALL_APPS_HEADER_FADE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AnimType {}
+ public static final int ANIM_VERTICAL_PROGRESS = 0;
+ public static final int ANIM_WORKSPACE_SCALE = 1;
+ public static final int ANIM_WORKSPACE_TRANSLATE = 2;
+ public static final int ANIM_WORKSPACE_FADE = 3;
+ public static final int ANIM_HOTSEAT_SCALE = 4;
+ public static final int ANIM_HOTSEAT_TRANSLATE = 5;
+ public static final int ANIM_OVERVIEW_SCALE = 6;
+ public static final int ANIM_OVERVIEW_TRANSLATE_X = 7;
+ public static final int ANIM_OVERVIEW_TRANSLATE_Y = 8;
+ public static final int ANIM_OVERVIEW_FADE = 9;
+ public static final int ANIM_ALL_APPS_FADE = 10;
+ public static final int ANIM_OVERVIEW_SCRIM_FADE = 11;
+ public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions
+
+ private static final int ANIM_TYPES_COUNT = 13;
+
+ private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
+
+ public StateAnimationConfig() { }
+
+ /**
+ * Copies the config to target
+ */
+ public void copyTo(StateAnimationConfig target) {
+ target.duration = duration;
+ target.animFlags = animFlags;
+ target.userControlled = userControlled;
+ for (int i = 0; i < ANIM_TYPES_COUNT; i++) {
+ target.mInterpolators[i] = mInterpolators[i];
+ }
+ }
+
+ /**
+ * Returns the interpolator set for animId or fallback if nothing is set
+ *
+ * @see #setInterpolator(int, Interpolator)
+ */
+ public Interpolator getInterpolator(@AnimType int animId, Interpolator fallback) {
+ return mInterpolators[animId] == null ? fallback : mInterpolators[animId];
+ }
+
+ /**
+ * Sets an interpolator for a given animation type
+ */
+ public void setInterpolator(@AnimType int animId, Interpolator interpolator) {
+ mInterpolators[animId] = interpolator;
+ }
+
+ /**
+ * @return Whether Overview is scaling as part of this animation. If this is the only
+ * component (i.e. NON_ATOMIC_COMPONENT isn't included), then this scaling is happening
+ * atomically, rather than being part of a normal state animation. StateHandlers can use
+ * this to designate part of their animation that should scale with Overview.
+ */
+ public boolean playAtomicOverviewScaleComponent() {
+ return hasAnimationFlag(StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE);
+ }
+
+ /**
+ * @return Whether this animation will play atomically at the same time as a different,
+ * user-controlled state transition. StateHandlers, which contribute to both animations, can
+ * use this to avoid animating the same properties in both animations, since they'd conflict
+ * with one another.
+ */
+ public boolean onlyPlayAtomicComponent() {
+ return getAnimComponents() == StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE
+ || getAnimComponents() == StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
+ }
+
+ /**
+ * Returns true if the config and any of the provided component flags
+ */
+ public boolean hasAnimationFlag(@AnimationFlags int a) {
+ return (animFlags & a) != 0;
+ }
+
+ /**
+ * @return Only the flags that determine which animation components to play.
+ */
+ public @AnimationFlags int getAnimComponents() {
+ return animFlags & StateAnimationConfig.ANIM_ALL_COMPONENTS;
+ }
+}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index c3664c3..cbc5257 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -19,11 +19,11 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherStateManager.ANIM_ALL_COMPONENTS;
-import static com.android.launcher3.LauncherStateManager.PLAY_ATOMIC_OVERVIEW_SCALE;
-import static com.android.launcher3.LauncherStateManager.PLAY_NON_ATOMIC;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.PLAY_NON_ATOMIC;
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
import android.animation.Animator;
@@ -37,12 +37,12 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationFlags;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -358,14 +358,18 @@
private AnimatorSet createAtomicAnimForState(LauncherState fromState, LauncherState targetState,
long duration) {
- AnimatorSetBuilder builder = getAnimatorSetBuilderForStates(fromState, targetState);
- return mLauncher.getStateManager().createAtomicAnimation(fromState, targetState, builder,
- PLAY_ATOMIC_OVERVIEW_SCALE, duration);
+ StateAnimationConfig config = getConfigForStates(fromState, targetState);
+ config.animFlags = PLAY_ATOMIC_OVERVIEW_SCALE;
+ config.duration = duration;
+ return mLauncher.getStateManager().createAtomicAnimation(fromState, targetState, config);
}
- protected AnimatorSetBuilder getAnimatorSetBuilderForStates(LauncherState fromState,
- LauncherState toState) {
- return new AnimatorSetBuilder();
+ /**
+ * Returns animation config for state transition between provided states
+ */
+ protected StateAnimationConfig getConfigForStates(
+ LauncherState fromState, LauncherState toState) {
+ return new StateAnimationConfig();
}
@Override
@@ -531,7 +535,7 @@
// case the user started interacting with it before the animation finished.
mLauncher.getStateManager().goToState(targetState, false /* animated */);
}
- mLauncher.getDragLayer().getScrim().animateToSysuiMultiplier(1, 0, 0);
+ mLauncher.getDragLayer().getScrim().createSysuiMultiplierAnim(1f).setDuration(0).start();
}
private void logReachedState(int logAction, LauncherState targetState) {
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 8d5f33d..4a202b6 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -23,7 +23,7 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.LauncherStateManager.AnimationFlags;
+import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
/**
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index a7078a2..8d1a3b0 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -16,8 +16,8 @@
package com.android.launcher3.widget;
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
@@ -28,16 +28,15 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.Interpolator;
import android.widget.TextView;
-import androidx.annotation.Nullable;
-
import com.android.launcher3.Insettable;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
-import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.PackageUserKey;
@@ -156,7 +155,7 @@
setupNavBarColor();
mOpenCloseAnimator.setValues(
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
- mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN);
mOpenCloseAnimator.start();
}
@@ -191,9 +190,9 @@
mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
}
- @Nullable
@Override
- public Animator createHintCloseAnim(float distanceToMove) {
- return ObjectAnimator.ofInt(this, PADDING_BOTTOM, (int) (distanceToMove + mInsets.bottom));
+ public void addHintCloseAnim(
+ float distanceToMove, Interpolator interpolator, PendingAnimation target) {
+ target.setInt(this, PADDING_BOTTOM, (int) (distanceToMove + mInsets.bottom), interpolator);
}
}
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index 2a102d2..b07a4f4 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -15,12 +15,11 @@
*/
package com.android.launcher3.widget;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
@@ -30,8 +29,8 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
-import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.Insettable;
@@ -39,6 +38,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener;
import com.android.launcher3.R;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.TopRoundedCornerView;
@@ -242,13 +242,11 @@
return mAdapter.getItemCount();
}
- @Nullable
@Override
- public Animator createHintCloseAnim(float distanceToMove) {
- AnimatorSet anim = new AnimatorSet();
- anim.play(ObjectAnimator.ofFloat(mRecyclerView, TRANSLATION_Y, -distanceToMove));
- anim.play(ObjectAnimator.ofFloat(mRecyclerView, ALPHA, 0.5f));
- return anim;
+ public void addHintCloseAnim(
+ float distanceToMove, Interpolator interpolator, PendingAnimation target) {
+ target.setFloat(mRecyclerView, VIEW_TRANSLATE_Y, -distanceToMove, interpolator);
+ target.setViewAlpha(mRecyclerView, 0.5f, interpolator);
}
@Override
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/BackgroundBlurController.java b/src_ui_overrides/com/android/launcher3/uioverrides/BackgroundBlurController.java
index 232bad3..75f99a9 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/BackgroundBlurController.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/BackgroundBlurController.java
@@ -19,10 +19,12 @@
import android.util.IntProperty;
import android.view.View;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
-import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.states.StateAnimationConfig;
/**
* Controls the blur, for the Launcher surface only.
@@ -52,6 +54,6 @@
public void setState(LauncherState toState) {}
@Override
- public void setStateWithAnimation(LauncherState toState, AnimatorSetBuilder builder,
- LauncherStateManager.AnimationConfig config) {}
+ public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
+ PendingAnimation animation) { }
}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java b/src_ui_overrides/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java
new file mode 100644
index 0000000..4913cad
--- /dev/null
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/PreviewSurfaceRenderer.java
@@ -0,0 +1,27 @@
+/*
+ * 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.uioverrides;
+
+import android.content.Context;
+import android.os.Bundle;
+
+/** Render preview using surface view. */
+public class PreviewSurfaceRenderer {
+
+ /** Handle a received surface view request. */
+ public static void render(Context context, Bundle bundle) { }
+}