Loading quickstep/src/com/android/launcher3/LauncherAnimationRunner.java +10 −6 Original line number Diff line number Diff line Loading @@ -152,16 +152,18 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo @UiThread public void setAnimation(AnimatorSet animation, Context context) { setAnimation(animation, context, null); setAnimation(animation, context, null, true); } /** * Sets the animation to play for this app launch * @param skipFirstFrame Iff true, we skip the first frame of the animation. * We set to false when skipping first frame causes jank. */ @UiThread public void setAnimation(AnimatorSet animation, Context context, @Nullable Runnable onCompleteCallback) { @Nullable Runnable onCompleteCallback, boolean skipFirstFrame) { if (mInitialized) { throw new IllegalStateException("Animation already initialized"); } Loading @@ -187,6 +189,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo }); mAnimator.start(); if (skipFirstFrame) { // Because t=0 has the app icon in its original spot, we can skip the // first frame and have the same movement one frame earlier. mAnimator.setCurrentPlayTime( Loading @@ -195,3 +198,4 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo } } } } quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +35 −12 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION; import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY; import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS; import static com.android.launcher3.statehandlers.DepthController.DEPTH; import static com.android.launcher3.util.DisplayController.getSingleFrameMs; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch; import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius; Loading Loading @@ -340,12 +341,17 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener final int rotationChange = getRotationChange(appTargets); // Note: the targetBounds are relative to the launcher int startDelay = getSingleFrameMs(mLauncher); Rect windowTargetBounds = getWindowTargetBounds(appTargets, rotationChange); anim.play(getOpeningWindowAnimators(v, appTargets, wallpaperTargets, nonAppTargets, windowTargetBounds, areAllTargetsTranslucent(appTargets), rotationChange)); Animator windowAnimator = getOpeningWindowAnimators(v, appTargets, wallpaperTargets, nonAppTargets, windowTargetBounds, areAllTargetsTranslucent(appTargets), rotationChange); windowAnimator.setStartDelay(startDelay); anim.play(windowAnimator); if (launcherClosing) { // Delay animation by a frame to avoid jank. Pair<AnimatorSet, Runnable> launcherContentAnimator = getLauncherContentAnimator(true /* isAppOpening */); getLauncherContentAnimator(true /* isAppOpening */, startDelay); anim.play(launcherContentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override Loading Loading @@ -436,8 +442,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener * * @param isAppOpening True when this is called when an app is opening. * False when this is called when an app is closing. * @param startDelay Start delay duration. */ private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening) { private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening, int startDelay) { AnimatorSet launcherAnimator = new AnimatorSet(); Runnable endListener; Loading Loading @@ -528,6 +536,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd(); }; } launcherAnimator.setStartDelay(startDelay); return new Pair<>(launcherAnimator, endListener); } Loading Loading @@ -633,7 +643,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener ? 0 : getWindowCornerRadius(mLauncher.getResources()); final float finalShadowRadius = appTargetsAreTranslucent ? 0 : mMaxShadowRadius; appAnimator.addUpdateListener(new MultiValueUpdateListener() { MultiValueUpdateListener listener = new MultiValueUpdateListener() { FloatProp mDx = new FloatProp(0, prop.dX, 0, prop.xDuration, AGGRESSIVE_EASE); FloatProp mDy = new FloatProp(0, prop.dY, 0, prop.yDuration, AGGRESSIVE_EASE); Loading Loading @@ -662,7 +672,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { // Calculate the size of the scaled icon. float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value; float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value; Loading Loading @@ -707,6 +717,12 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener floatingIconBounds.right += offsetX; floatingIconBounds.bottom += offsetY; if (initOnly) { floatingView.update(mIconAlpha.value, 255, floatingIconBounds, percent, 0f, mWindowRadius.value * scale, true /* isOpening */); return; } ArrayList<SurfaceParams> params = new ArrayList<>(); for (int i = appTargets.length - 1; i >= 0; i--) { RemoteAnimationTargetCompat target = appTargets[i]; Loading Loading @@ -779,7 +795,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[params.size()])); } }); }; appAnimator.addUpdateListener(listener); // Since we added a start delay, call update here to init the FloatingIconView properly. listener.onUpdate(0, true /* initOnly */); animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets)); return animatorSet; Loading Loading @@ -869,7 +888,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { widgetBackgroundBounds.set(mDx.value - mWidth.value / 2f, mDy.value - mHeight.value / 2f, mDx.value + mWidth.value / 2f, mDy.value + mHeight.value / 2f); Loading Loading @@ -1128,7 +1147,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener DEACCEL_1_7); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { SurfaceParams[] params = new SurfaceParams[appTargets.length]; for (int i = appTargets.length - 1; i >= 0; i--) { RemoteAnimationTargetCompat target = appTargets[i]; Loading Loading @@ -1278,8 +1297,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener if (mLauncher.isInState(LauncherState.ALL_APPS)) { Pair<AnimatorSet, Runnable> contentAnimator = getLauncherContentAnimator(false /* isAppOpening */); contentAnimator.first.setStartDelay(LAUNCHER_RESUME_START_DELAY); getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override Loading Loading @@ -1328,27 +1346,32 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener final boolean launchingFromWidget = mV instanceof LauncherAppWidgetHostView; final boolean launchingFromRecents = isLaunchingFromRecents(mV, appTargets); final boolean skipFirstFrame; if (launchingFromWidget) { composeWidgetLaunchAnimator(anim, (LauncherAppWidgetHostView) mV, appTargets, wallpaperTargets, nonAppTargets); addCujInstrumentation( anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_WIDGET); skipFirstFrame = true; } else if (launchingFromRecents) { composeRecentsLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets, launcherClosing); addCujInstrumentation( anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_RECENTS); skipFirstFrame = true; } else { composeIconLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets, launcherClosing); addCujInstrumentation(anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_ICON); skipFirstFrame = false; } if (launcherClosing) { anim.addListener(mForceInvisibleListener); } result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy); result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy, skipFirstFrame); } } Loading quickstep/src/com/android/quickstep/RecentsActivity.java +4 −2 Original line number Diff line number Diff line Loading @@ -214,7 +214,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> { AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets, wallpaperTargets, nonAppTargets); anim.addListener(resetStateListener()); result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy); result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy, true /* skipFirstFrame */); }; final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner<>( Loading Loading @@ -386,7 +387,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> { anim.play(controller.getAnimationPlayer()); anim.setDuration(HOME_APPEAR_DURATION); result.setAnimation(anim, this, () -> getStateManager().goToState(RecentsState.HOME, false)); () -> getStateManager().goToState(RecentsState.HOME, false), true /* skipFirstFrame */); } @Override Loading quickstep/src/com/android/quickstep/TaskViewUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -249,7 +249,7 @@ public final class TaskViewUtils { ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { final SurfaceParams.Builder navBuilder = new SurfaceParams.Builder(navBarTarget.leash); if (mNavFadeIn.value > mNavFadeIn.getStartValue()) { Loading quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java +6 −2 Original line number Diff line number Diff line Loading @@ -40,10 +40,14 @@ public abstract class MultiValueUpdateListener implements ValueAnimator.Animator newPercent = prop.mInterpolator.getInterpolation(newPercent); prop.value = prop.mEnd * newPercent + prop.mStart * (1 - newPercent); } onUpdate(percent); onUpdate(percent, false /* initOnly */); } public abstract void onUpdate(float percent); /** * @param percent The total animation progress. * @param initOnly When true, only does enough work to initialize the animation. */ public abstract void onUpdate(float percent, boolean initOnly); public final class FloatProp { Loading Loading
quickstep/src/com/android/launcher3/LauncherAnimationRunner.java +10 −6 Original line number Diff line number Diff line Loading @@ -152,16 +152,18 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo @UiThread public void setAnimation(AnimatorSet animation, Context context) { setAnimation(animation, context, null); setAnimation(animation, context, null, true); } /** * Sets the animation to play for this app launch * @param skipFirstFrame Iff true, we skip the first frame of the animation. * We set to false when skipping first frame causes jank. */ @UiThread public void setAnimation(AnimatorSet animation, Context context, @Nullable Runnable onCompleteCallback) { @Nullable Runnable onCompleteCallback, boolean skipFirstFrame) { if (mInitialized) { throw new IllegalStateException("Animation already initialized"); } Loading @@ -187,6 +189,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo }); mAnimator.start(); if (skipFirstFrame) { // Because t=0 has the app icon in its original spot, we can skip the // first frame and have the same movement one frame earlier. mAnimator.setCurrentPlayTime( Loading @@ -195,3 +198,4 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo } } } }
quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +35 −12 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION; import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY; import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS; import static com.android.launcher3.statehandlers.DepthController.DEPTH; import static com.android.launcher3.util.DisplayController.getSingleFrameMs; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch; import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius; Loading Loading @@ -340,12 +341,17 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener final int rotationChange = getRotationChange(appTargets); // Note: the targetBounds are relative to the launcher int startDelay = getSingleFrameMs(mLauncher); Rect windowTargetBounds = getWindowTargetBounds(appTargets, rotationChange); anim.play(getOpeningWindowAnimators(v, appTargets, wallpaperTargets, nonAppTargets, windowTargetBounds, areAllTargetsTranslucent(appTargets), rotationChange)); Animator windowAnimator = getOpeningWindowAnimators(v, appTargets, wallpaperTargets, nonAppTargets, windowTargetBounds, areAllTargetsTranslucent(appTargets), rotationChange); windowAnimator.setStartDelay(startDelay); anim.play(windowAnimator); if (launcherClosing) { // Delay animation by a frame to avoid jank. Pair<AnimatorSet, Runnable> launcherContentAnimator = getLauncherContentAnimator(true /* isAppOpening */); getLauncherContentAnimator(true /* isAppOpening */, startDelay); anim.play(launcherContentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override Loading Loading @@ -436,8 +442,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener * * @param isAppOpening True when this is called when an app is opening. * False when this is called when an app is closing. * @param startDelay Start delay duration. */ private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening) { private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening, int startDelay) { AnimatorSet launcherAnimator = new AnimatorSet(); Runnable endListener; Loading Loading @@ -528,6 +536,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd(); }; } launcherAnimator.setStartDelay(startDelay); return new Pair<>(launcherAnimator, endListener); } Loading Loading @@ -633,7 +643,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener ? 0 : getWindowCornerRadius(mLauncher.getResources()); final float finalShadowRadius = appTargetsAreTranslucent ? 0 : mMaxShadowRadius; appAnimator.addUpdateListener(new MultiValueUpdateListener() { MultiValueUpdateListener listener = new MultiValueUpdateListener() { FloatProp mDx = new FloatProp(0, prop.dX, 0, prop.xDuration, AGGRESSIVE_EASE); FloatProp mDy = new FloatProp(0, prop.dY, 0, prop.yDuration, AGGRESSIVE_EASE); Loading Loading @@ -662,7 +672,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { // Calculate the size of the scaled icon. float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value; float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value; Loading Loading @@ -707,6 +717,12 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener floatingIconBounds.right += offsetX; floatingIconBounds.bottom += offsetY; if (initOnly) { floatingView.update(mIconAlpha.value, 255, floatingIconBounds, percent, 0f, mWindowRadius.value * scale, true /* isOpening */); return; } ArrayList<SurfaceParams> params = new ArrayList<>(); for (int i = appTargets.length - 1; i >= 0; i--) { RemoteAnimationTargetCompat target = appTargets[i]; Loading Loading @@ -779,7 +795,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[params.size()])); } }); }; appAnimator.addUpdateListener(listener); // Since we added a start delay, call update here to init the FloatingIconView properly. listener.onUpdate(0, true /* initOnly */); animatorSet.playTogether(appAnimator, getBackgroundAnimator(appTargets)); return animatorSet; Loading Loading @@ -869,7 +888,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { widgetBackgroundBounds.set(mDx.value - mWidth.value / 2f, mDy.value - mHeight.value / 2f, mDx.value + mWidth.value / 2f, mDy.value + mHeight.value / 2f); Loading Loading @@ -1128,7 +1147,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener DEACCEL_1_7); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { SurfaceParams[] params = new SurfaceParams[appTargets.length]; for (int i = appTargets.length - 1; i >= 0; i--) { RemoteAnimationTargetCompat target = appTargets[i]; Loading Loading @@ -1278,8 +1297,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener if (mLauncher.isInState(LauncherState.ALL_APPS)) { Pair<AnimatorSet, Runnable> contentAnimator = getLauncherContentAnimator(false /* isAppOpening */); contentAnimator.first.setStartDelay(LAUNCHER_RESUME_START_DELAY); getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY); anim.play(contentAnimator.first); anim.addListener(new AnimatorListenerAdapter() { @Override Loading Loading @@ -1328,27 +1346,32 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener final boolean launchingFromWidget = mV instanceof LauncherAppWidgetHostView; final boolean launchingFromRecents = isLaunchingFromRecents(mV, appTargets); final boolean skipFirstFrame; if (launchingFromWidget) { composeWidgetLaunchAnimator(anim, (LauncherAppWidgetHostView) mV, appTargets, wallpaperTargets, nonAppTargets); addCujInstrumentation( anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_WIDGET); skipFirstFrame = true; } else if (launchingFromRecents) { composeRecentsLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets, launcherClosing); addCujInstrumentation( anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_RECENTS); skipFirstFrame = true; } else { composeIconLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets, launcherClosing); addCujInstrumentation(anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_ICON); skipFirstFrame = false; } if (launcherClosing) { anim.addListener(mForceInvisibleListener); } result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy); result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy, skipFirstFrame); } } Loading
quickstep/src/com/android/quickstep/RecentsActivity.java +4 −2 Original line number Diff line number Diff line Loading @@ -214,7 +214,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> { AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets, wallpaperTargets, nonAppTargets); anim.addListener(resetStateListener()); result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy); result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy, true /* skipFirstFrame */); }; final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner<>( Loading Loading @@ -386,7 +387,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> { anim.play(controller.getAnimationPlayer()); anim.setDuration(HOME_APPEAR_DURATION); result.setAnimation(anim, this, () -> getStateManager().goToState(RecentsState.HOME, false)); () -> getStateManager().goToState(RecentsState.HOME, false), true /* skipFirstFrame */); } @Override Loading
quickstep/src/com/android/quickstep/TaskViewUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -249,7 +249,7 @@ public final class TaskViewUtils { ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); @Override public void onUpdate(float percent) { public void onUpdate(float percent, boolean initOnly) { final SurfaceParams.Builder navBuilder = new SurfaceParams.Builder(navBarTarget.leash); if (mNavFadeIn.value > mNavFadeIn.getStartValue()) { Loading
quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java +6 −2 Original line number Diff line number Diff line Loading @@ -40,10 +40,14 @@ public abstract class MultiValueUpdateListener implements ValueAnimator.Animator newPercent = prop.mInterpolator.getInterpolation(newPercent); prop.value = prop.mEnd * newPercent + prop.mStart * (1 - newPercent); } onUpdate(percent); onUpdate(percent, false /* initOnly */); } public abstract void onUpdate(float percent); /** * @param percent The total animation progress. * @param initOnly When true, only does enough work to initialize the animation. */ public abstract void onUpdate(float percent, boolean initOnly); public final class FloatProp { Loading