Loading Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ android_library { srcs: [ srcs: [ "tests/tapl/**/*.java", "tests/tapl/**/*.java", "src/com/android/launcher3/util/SecureSettingsObserver.java", "src/com/android/launcher3/util/SecureSettingsObserver.java", "src/com/android/launcher3/ResourceUtils.java", "src/com/android/launcher3/TestProtocol.java", "src/com/android/launcher3/TestProtocol.java", ], ], manifest: "tests/tapl/AndroidManifest.xml", manifest: "tests/tapl/AndroidManifest.xml", Loading go/quickstep/res/values-sw480dp/dimens.xml +4 −4 Original line number Original line Diff line number Diff line Loading @@ -18,13 +18,13 @@ <dimen name="recents_list_width">480dp</dimen> <dimen name="recents_list_width">480dp</dimen> <dimen name="task_item_height">90dp</dimen> <dimen name="task_item_height">90dp</dimen> <dimen name="task_item_top_margin">16dp</dimen> <dimen name="task_item_top_margin">24dp</dimen> <dimen name="task_thumbnail_icon_horiz_margin">20dp</dimen> <dimen name="task_thumbnail_icon_horiz_margin">24dp</dimen> <dimen name="task_thumbnail_corner_radius">4dp</dimen> <dimen name="task_thumbnail_corner_radius">4dp</dimen> <dimen name="clear_all_item_view_height">48dp</dimen> <dimen name="clear_all_item_view_height">52dp</dimen> <dimen name="clear_all_item_view_top_margin">28dp</dimen> <dimen name="clear_all_item_view_top_margin">28dp</dimen> <dimen name="clear_all_item_view_bottom_margin">28dp</dimen> <dimen name="clear_all_item_view_bottom_margin">28dp</dimen> <dimen name="clear_all_button_width">140dp</dimen> <dimen name="clear_all_button_width">160dp</dimen> </resources> </resources> No newline at end of file go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java +41 −1 Original line number Original line Diff line number Diff line package com.android.launcher3; package com.android.launcher3; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ObjectAnimator; import android.app.ActivityOptions; import android.content.Context; import android.content.Context; import android.os.Handler; import android.view.View; import android.view.View; import com.android.quickstep.views.IconRecentsView; import com.android.quickstep.views.IconRecentsView; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; /** /** Loading @@ -28,6 +32,12 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager().getState().overviewUi; return mLauncher.getStateManager().getState().overviewUi; } } @Override RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new GoWallpaperOpenLauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */, fromUnlock); } @Override @Override protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { Loading @@ -51,4 +61,34 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager()::reapplyState; return mLauncher.getStateManager()::reapplyState; } } /** * Remote animation runner for animation from app to Launcher. For Go, when going to recents, * we need to ensure that the recents view is ready for remote animation before starting. */ private final class GoWallpaperOpenLauncherAnimationRunner extends WallpaperOpenLauncherAnimationRunner { public GoWallpaperOpenLauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue, boolean fromUnlock) { super(handler, startAtFrontOfQueue, fromUnlock); } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { boolean isGoingToRecents = taskIsATargetWithMode(targetCompats, mLauncher.getTaskId(), MODE_OPENING) && (mLauncher.getStateManager().getState() == LauncherState.OVERVIEW); if (isGoingToRecents) { IconRecentsView recentsView = mLauncher.getOverviewPanel(); if (!recentsView.isReadyForRemoteAnim()) { recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result)) ); return; } } super.onCreateAnimation(targetCompats, result); } } } } go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -21,10 +21,12 @@ import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import android.view.View; import android.view.View; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.Utilities; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController; Loading Loading @@ -102,4 +104,8 @@ public abstract class RecentsUiFactory { * @param launcher the launcher activity * @param launcher the launcher activity */ */ public static void onLauncherStateOrResumeChanged(Launcher launcher) {} public static void onLauncherStateOrResumeChanged(Launcher launcher) {} public static RotationMode getRotationMode(DeviceProfile dp) { return RotationMode.NORMAL; } } } go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java +64 −99 Original line number Original line Diff line number Diff line Loading @@ -15,30 +15,27 @@ */ */ package com.android.quickstep; package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.quickstep.util.RemoteAnimationProvider.getLayer; import static com.android.quickstep.views.IconRecentsView.REMOTE_APP_TO_OVERVIEW_DURATION; 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_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.graphics.Matrix; import android.app.ActivityOptions; import android.graphics.Rect; import android.os.Handler; import android.util.Log; import android.util.Log; import android.view.View; import androidx.annotation.NonNull; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.launcher3.LauncherAnimationRunner; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.IconRecentsView; import com.android.quickstep.views.IconRecentsView; 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.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; /** /** * Provider for the atomic remote window animation from the app to the overview. * Provider for the atomic remote window animation from the app to the overview. Loading @@ -47,20 +44,27 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. */ */ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements RemoteAnimationProvider { RemoteAnimationProvider { private static final long APP_TO_THUMBNAIL_FADE_DURATION = 50; private static final long APP_SCALE_DOWN_DURATION = 400; private static final String TAG = "AppToOverviewAnimationProvider"; private static final String TAG = "AppToOverviewAnimationProvider"; private final ActivityControlHelper<T> mHelper; private final ActivityControlHelper<T> mHelper; private final int mTargetTaskId; private final int mTargetTaskId; private IconRecentsView mRecentsView; private IconRecentsView mRecentsView; private AppToOverviewAnimationListener mAnimationReadyListener; AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) { AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) { mHelper = helper; mHelper = helper; mTargetTaskId = targetTaskId; mTargetTaskId = targetTaskId; } } /** * Set listener to various points in the animation preparing to animate. * * @param listener listener */ void setAnimationListener(AppToOverviewAnimationListener listener) { mAnimationReadyListener = listener; } /** /** * Callback for when the activity is ready/initialized. * Callback for when the activity is ready/initialized. * * Loading @@ -68,6 +72,9 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple * @param wasVisible true if it was visible before * @param wasVisible true if it was visible before */ */ boolean onActivityReady(T activity, Boolean wasVisible) { boolean onActivityReady(T activity, Boolean wasVisible) { if (mAnimationReadyListener != null) { mAnimationReadyListener.onActivityReady(activity); } ActivityControlHelper.AnimationFactory factory = ActivityControlHelper.AnimationFactory factory = mHelper.prepareRecentsUI(activity, wasVisible, mHelper.prepareRecentsUI(activity, wasVisible, false /* animate activity */, (controller) -> { false /* animate activity */, (controller) -> { Loading @@ -92,6 +99,9 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple */ */ @Override @Override public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) { public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) { if (mAnimationReadyListener != null) { mAnimationReadyListener.onWindowAnimationCreated(); } AnimatorSet anim = new AnimatorSet(); AnimatorSet anim = new AnimatorSet(); if (mRecentsView == null) { if (mRecentsView == null) { if (Log.isLoggable(TAG, Log.WARN)) { if (Log.isLoggable(TAG, Log.WARN)) { Loading Loading @@ -131,98 +141,36 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple return anim; return anim; } } View thumbnailView = mRecentsView.getBottomThumbnailView(); if (closingAppTarget.activityType == ACTIVITY_TYPE_HOME) { if (thumbnailView == null) { mRecentsView.playRemoteHomeToRecentsAnimation(anim, closingAppTarget, recentsTarget); // This can be null if there were previously 0 tasks and the recycler view has not had } else { // enough time to take in the data change, bind a new view, and lay out the new view. mRecentsView.playRemoteAppToRecentsAnimation(anim, closingAppTarget, recentsTarget); // TODO: Have a fallback to animate to if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "No thumbnail view for running task. Using stub animation."); } anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration())); return anim; } } playAppScaleDownAnim(anim, closingAppTarget, recentsTarget, thumbnailView); return anim; return anim; } } /** * Animate a closing app to scale down to the location of the thumbnail view in recents. * * @param anim animator set * @param appTarget the app surface thats closing * @param recentsTarget the surface containing recents * @param thumbnailView the thumbnail view to animate to */ private void playAppScaleDownAnim(@NonNull AnimatorSet anim, @NonNull RemoteAnimationTargetCompat appTarget, @NonNull RemoteAnimationTargetCompat recentsTarget, @NonNull View thumbnailView) { // Identify where the entering remote app should animate to. Rect endRect = new Rect(); thumbnailView.getGlobalVisibleRect(endRect); Rect appBounds = appTarget.sourceContainerBounds; ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1); valueAnimator.setDuration(APP_SCALE_DOWN_DURATION); SyncRtSurfaceTransactionApplierCompat surfaceApplier = new SyncRtSurfaceTransactionApplierCompat(thumbnailView); // Keep recents visible throughout the animation. SurfaceParams[] params = new SurfaceParams[2]; // Closing app should stay on top. int boostedMode = MODE_CLOSING; params[0] = new SurfaceParams(recentsTarget.leash, 1f, null /* matrix */, null /* windowCrop */, getLayer(recentsTarget, boostedMode), 0 /* cornerRadius */); valueAnimator.addUpdateListener(new MultiValueUpdateListener() { private final FloatProp mScaleX; private final FloatProp mScaleY; private final FloatProp mTranslationX; private final FloatProp mTranslationY; private final FloatProp mAlpha; { // Scale down and move to view location. float endScaleX = ((float) endRect.width()) / appBounds.width(); mScaleX = new FloatProp(1f, endScaleX, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); float endScaleY = ((float) endRect.height()) / appBounds.height(); mScaleY = new FloatProp(1f, endScaleY, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); float endTranslationX = endRect.left - (appBounds.width() - thumbnailView.getWidth()) / 2.0f; mTranslationX = new FloatProp(0, endTranslationX, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); float endTranslationY = endRect.top - (appBounds.height() - thumbnailView.getHeight()) / 2.0f; mTranslationY = new FloatProp(0, endTranslationY, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); // Fade out quietly near the end to be replaced by the real view. mAlpha = new FloatProp(1.0f, 0, APP_SCALE_DOWN_DURATION - APP_TO_THUMBNAIL_FADE_DURATION, APP_TO_THUMBNAIL_FADE_DURATION, ACCEL_2); } @Override @Override public void onUpdate(float percent) { public ActivityOptions toActivityOptions(Handler handler, long duration) { Matrix m = new Matrix(); LauncherAnimationRunner runner = new LauncherAnimationRunner(handler, m.setScale(mScaleX.value, mScaleY.value, false /* startAtFrontOfQueue */) { appBounds.width() / 2.0f, appBounds.height() / 2.0f); m.postTranslate(mTranslationX.value, mTranslationY.value); params[1] = new SurfaceParams(appTarget.leash, mAlpha.value, m, @Override null /* windowCrop */, getLayer(appTarget, boostedMode), public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, 0 /* cornerRadius */); AnimationResult result) { surfaceApplier.scheduleApply(params); IconRecentsView recentsView = mRecentsView; if (!recentsView.isReadyForRemoteAnim()) { recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(handler, () -> onCreateAnimation(targetCompats, result)) ); return; } } }); result.setAnimation(createWindowAnimation(targetCompats)); anim.play(valueAnimator); } }; return ActivityOptionsCompat.makeRemoteAnimation( new RemoteAnimationAdapterCompat(runner, duration, 0 /* statusBarTransitionDelay */)); } } /** /** Loading @@ -231,6 +179,23 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple * @return duration of animation * @return duration of animation */ */ long getRecentsLaunchDuration() { long getRecentsLaunchDuration() { return APP_SCALE_DOWN_DURATION; return REMOTE_APP_TO_OVERVIEW_DURATION; } /** * Listener for various points in the app to overview animation preparing to animate. */ interface AppToOverviewAnimationListener { /** * Logic for when activity we're animating to is ready * * @param activity activity to animate to */ void onActivityReady(BaseDraggingActivity activity); /** * Logic for when we've created the app to recents animation. */ void onWindowAnimationCreated(); } } } } Loading
Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ android_library { srcs: [ srcs: [ "tests/tapl/**/*.java", "tests/tapl/**/*.java", "src/com/android/launcher3/util/SecureSettingsObserver.java", "src/com/android/launcher3/util/SecureSettingsObserver.java", "src/com/android/launcher3/ResourceUtils.java", "src/com/android/launcher3/TestProtocol.java", "src/com/android/launcher3/TestProtocol.java", ], ], manifest: "tests/tapl/AndroidManifest.xml", manifest: "tests/tapl/AndroidManifest.xml", Loading
go/quickstep/res/values-sw480dp/dimens.xml +4 −4 Original line number Original line Diff line number Diff line Loading @@ -18,13 +18,13 @@ <dimen name="recents_list_width">480dp</dimen> <dimen name="recents_list_width">480dp</dimen> <dimen name="task_item_height">90dp</dimen> <dimen name="task_item_height">90dp</dimen> <dimen name="task_item_top_margin">16dp</dimen> <dimen name="task_item_top_margin">24dp</dimen> <dimen name="task_thumbnail_icon_horiz_margin">20dp</dimen> <dimen name="task_thumbnail_icon_horiz_margin">24dp</dimen> <dimen name="task_thumbnail_corner_radius">4dp</dimen> <dimen name="task_thumbnail_corner_radius">4dp</dimen> <dimen name="clear_all_item_view_height">48dp</dimen> <dimen name="clear_all_item_view_height">52dp</dimen> <dimen name="clear_all_item_view_top_margin">28dp</dimen> <dimen name="clear_all_item_view_top_margin">28dp</dimen> <dimen name="clear_all_item_view_bottom_margin">28dp</dimen> <dimen name="clear_all_item_view_bottom_margin">28dp</dimen> <dimen name="clear_all_button_width">140dp</dimen> <dimen name="clear_all_button_width">160dp</dimen> </resources> </resources> No newline at end of file
go/quickstep/src/com/android/launcher3/GoLauncherAppTransitionManagerImpl.java +41 −1 Original line number Original line Diff line number Diff line package com.android.launcher3; package com.android.launcher3; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.IconRecentsView.CONTENT_ALPHA; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ObjectAnimator; import android.app.ActivityOptions; import android.content.Context; import android.content.Context; import android.os.Handler; import android.view.View; import android.view.View; import com.android.quickstep.views.IconRecentsView; import com.android.quickstep.views.IconRecentsView; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; /** /** Loading @@ -28,6 +32,12 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager().getState().overviewUi; return mLauncher.getStateManager().getState().overviewUi; } } @Override RemoteAnimationRunnerCompat getWallpaperOpenRunner(boolean fromUnlock) { return new GoWallpaperOpenLauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */, fromUnlock); } @Override @Override protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { Loading @@ -51,4 +61,34 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi return mLauncher.getStateManager()::reapplyState; return mLauncher.getStateManager()::reapplyState; } } /** * Remote animation runner for animation from app to Launcher. For Go, when going to recents, * we need to ensure that the recents view is ready for remote animation before starting. */ private final class GoWallpaperOpenLauncherAnimationRunner extends WallpaperOpenLauncherAnimationRunner { public GoWallpaperOpenLauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue, boolean fromUnlock) { super(handler, startAtFrontOfQueue, fromUnlock); } @Override public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, AnimationResult result) { boolean isGoingToRecents = taskIsATargetWithMode(targetCompats, mLauncher.getTaskId(), MODE_OPENING) && (mLauncher.getStateManager().getState() == LauncherState.OVERVIEW); if (isGoingToRecents) { IconRecentsView recentsView = mLauncher.getOverviewPanel(); if (!recentsView.isReadyForRemoteAnim()) { recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result)) ); return; } } super.onCreateAnimation(targetCompats, result); } } } }
go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -21,10 +21,12 @@ import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import android.view.View; import android.view.View; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.Utilities; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController; Loading Loading @@ -102,4 +104,8 @@ public abstract class RecentsUiFactory { * @param launcher the launcher activity * @param launcher the launcher activity */ */ public static void onLauncherStateOrResumeChanged(Launcher launcher) {} public static void onLauncherStateOrResumeChanged(Launcher launcher) {} public static RotationMode getRotationMode(DeviceProfile dp) { return RotationMode.NORMAL; } } }
go/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java +64 −99 Original line number Original line Diff line number Diff line Loading @@ -15,30 +15,27 @@ */ */ package com.android.quickstep; package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.quickstep.util.RemoteAnimationProvider.getLayer; import static com.android.quickstep.views.IconRecentsView.REMOTE_APP_TO_OVERVIEW_DURATION; 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_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import android.animation.AnimatorSet; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.graphics.Matrix; import android.app.ActivityOptions; import android.graphics.Rect; import android.os.Handler; import android.util.Log; import android.util.Log; import android.view.View; import androidx.annotation.NonNull; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.launcher3.LauncherAnimationRunner; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.IconRecentsView; import com.android.quickstep.views.IconRecentsView; 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.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; /** /** * Provider for the atomic remote window animation from the app to the overview. * Provider for the atomic remote window animation from the app to the overview. Loading @@ -47,20 +44,27 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. */ */ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements RemoteAnimationProvider { RemoteAnimationProvider { private static final long APP_TO_THUMBNAIL_FADE_DURATION = 50; private static final long APP_SCALE_DOWN_DURATION = 400; private static final String TAG = "AppToOverviewAnimationProvider"; private static final String TAG = "AppToOverviewAnimationProvider"; private final ActivityControlHelper<T> mHelper; private final ActivityControlHelper<T> mHelper; private final int mTargetTaskId; private final int mTargetTaskId; private IconRecentsView mRecentsView; private IconRecentsView mRecentsView; private AppToOverviewAnimationListener mAnimationReadyListener; AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) { AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) { mHelper = helper; mHelper = helper; mTargetTaskId = targetTaskId; mTargetTaskId = targetTaskId; } } /** * Set listener to various points in the animation preparing to animate. * * @param listener listener */ void setAnimationListener(AppToOverviewAnimationListener listener) { mAnimationReadyListener = listener; } /** /** * Callback for when the activity is ready/initialized. * Callback for when the activity is ready/initialized. * * Loading @@ -68,6 +72,9 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple * @param wasVisible true if it was visible before * @param wasVisible true if it was visible before */ */ boolean onActivityReady(T activity, Boolean wasVisible) { boolean onActivityReady(T activity, Boolean wasVisible) { if (mAnimationReadyListener != null) { mAnimationReadyListener.onActivityReady(activity); } ActivityControlHelper.AnimationFactory factory = ActivityControlHelper.AnimationFactory factory = mHelper.prepareRecentsUI(activity, wasVisible, mHelper.prepareRecentsUI(activity, wasVisible, false /* animate activity */, (controller) -> { false /* animate activity */, (controller) -> { Loading @@ -92,6 +99,9 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple */ */ @Override @Override public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) { public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) { if (mAnimationReadyListener != null) { mAnimationReadyListener.onWindowAnimationCreated(); } AnimatorSet anim = new AnimatorSet(); AnimatorSet anim = new AnimatorSet(); if (mRecentsView == null) { if (mRecentsView == null) { if (Log.isLoggable(TAG, Log.WARN)) { if (Log.isLoggable(TAG, Log.WARN)) { Loading Loading @@ -131,98 +141,36 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple return anim; return anim; } } View thumbnailView = mRecentsView.getBottomThumbnailView(); if (closingAppTarget.activityType == ACTIVITY_TYPE_HOME) { if (thumbnailView == null) { mRecentsView.playRemoteHomeToRecentsAnimation(anim, closingAppTarget, recentsTarget); // This can be null if there were previously 0 tasks and the recycler view has not had } else { // enough time to take in the data change, bind a new view, and lay out the new view. mRecentsView.playRemoteAppToRecentsAnimation(anim, closingAppTarget, recentsTarget); // TODO: Have a fallback to animate to if (Log.isLoggable(TAG, Log.WARN)) { Log.w(TAG, "No thumbnail view for running task. Using stub animation."); } anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration())); return anim; } } playAppScaleDownAnim(anim, closingAppTarget, recentsTarget, thumbnailView); return anim; return anim; } } /** * Animate a closing app to scale down to the location of the thumbnail view in recents. * * @param anim animator set * @param appTarget the app surface thats closing * @param recentsTarget the surface containing recents * @param thumbnailView the thumbnail view to animate to */ private void playAppScaleDownAnim(@NonNull AnimatorSet anim, @NonNull RemoteAnimationTargetCompat appTarget, @NonNull RemoteAnimationTargetCompat recentsTarget, @NonNull View thumbnailView) { // Identify where the entering remote app should animate to. Rect endRect = new Rect(); thumbnailView.getGlobalVisibleRect(endRect); Rect appBounds = appTarget.sourceContainerBounds; ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1); valueAnimator.setDuration(APP_SCALE_DOWN_DURATION); SyncRtSurfaceTransactionApplierCompat surfaceApplier = new SyncRtSurfaceTransactionApplierCompat(thumbnailView); // Keep recents visible throughout the animation. SurfaceParams[] params = new SurfaceParams[2]; // Closing app should stay on top. int boostedMode = MODE_CLOSING; params[0] = new SurfaceParams(recentsTarget.leash, 1f, null /* matrix */, null /* windowCrop */, getLayer(recentsTarget, boostedMode), 0 /* cornerRadius */); valueAnimator.addUpdateListener(new MultiValueUpdateListener() { private final FloatProp mScaleX; private final FloatProp mScaleY; private final FloatProp mTranslationX; private final FloatProp mTranslationY; private final FloatProp mAlpha; { // Scale down and move to view location. float endScaleX = ((float) endRect.width()) / appBounds.width(); mScaleX = new FloatProp(1f, endScaleX, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); float endScaleY = ((float) endRect.height()) / appBounds.height(); mScaleY = new FloatProp(1f, endScaleY, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); float endTranslationX = endRect.left - (appBounds.width() - thumbnailView.getWidth()) / 2.0f; mTranslationX = new FloatProp(0, endTranslationX, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); float endTranslationY = endRect.top - (appBounds.height() - thumbnailView.getHeight()) / 2.0f; mTranslationY = new FloatProp(0, endTranslationY, 0, APP_SCALE_DOWN_DURATION, ACCEL_DEACCEL); // Fade out quietly near the end to be replaced by the real view. mAlpha = new FloatProp(1.0f, 0, APP_SCALE_DOWN_DURATION - APP_TO_THUMBNAIL_FADE_DURATION, APP_TO_THUMBNAIL_FADE_DURATION, ACCEL_2); } @Override @Override public void onUpdate(float percent) { public ActivityOptions toActivityOptions(Handler handler, long duration) { Matrix m = new Matrix(); LauncherAnimationRunner runner = new LauncherAnimationRunner(handler, m.setScale(mScaleX.value, mScaleY.value, false /* startAtFrontOfQueue */) { appBounds.width() / 2.0f, appBounds.height() / 2.0f); m.postTranslate(mTranslationX.value, mTranslationY.value); params[1] = new SurfaceParams(appTarget.leash, mAlpha.value, m, @Override null /* windowCrop */, getLayer(appTarget, boostedMode), public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, 0 /* cornerRadius */); AnimationResult result) { surfaceApplier.scheduleApply(params); IconRecentsView recentsView = mRecentsView; if (!recentsView.isReadyForRemoteAnim()) { recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(handler, () -> onCreateAnimation(targetCompats, result)) ); return; } } }); result.setAnimation(createWindowAnimation(targetCompats)); anim.play(valueAnimator); } }; return ActivityOptionsCompat.makeRemoteAnimation( new RemoteAnimationAdapterCompat(runner, duration, 0 /* statusBarTransitionDelay */)); } } /** /** Loading @@ -231,6 +179,23 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple * @return duration of animation * @return duration of animation */ */ long getRecentsLaunchDuration() { long getRecentsLaunchDuration() { return APP_SCALE_DOWN_DURATION; return REMOTE_APP_TO_OVERVIEW_DURATION; } /** * Listener for various points in the app to overview animation preparing to animate. */ interface AppToOverviewAnimationListener { /** * Logic for when activity we're animating to is ready * * @param activity activity to animate to */ void onActivityReady(BaseDraggingActivity activity); /** * Logic for when we've created the app to recents animation. */ void onWindowAnimationCreated(); } } } }