diff options
Diffstat (limited to 'quickstep')
14 files changed, 323 insertions, 166 deletions
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar Binary files differindex 8af310c21..ab97344d1 100644 --- a/quickstep/libs/sysui_shared.jar +++ b/quickstep/libs/sysui_shared.jar diff --git a/quickstep/res/values/override.xml b/quickstep/recents_ui_overrides/res/values/override.xml index d6836594f..c60cf5ab6 100644 --- a/quickstep/res/values/override.xml +++ b/quickstep/recents_ui_overrides/res/values/override.xml @@ -14,6 +14,8 @@ limitations under the License. --> +<!-- Class overrides for launcher with quickstep. --> + <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_transition_manager_class" translatable="false">com.android.launcher3.LauncherAppTransitionManagerImpl</string> diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java new file mode 100644 index 000000000..9921455ca --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2018 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 static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.quickstep.TaskUtils.findTaskViewToLaunch; +import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.app.ActivityOptions; +import android.content.Context; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.anim.Interpolators; +import com.android.quickstep.util.ClipAnimationHelper; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskView; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; + +/** + * A {@link QuickstepAppTransitionManagerImpl} that also implements recents transitions from + * {@link RecentsView}. + */ +public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransitionManagerImpl { + + private RecentsView mRecentsView; + + public LauncherAppTransitionManagerImpl(Context context) { + super(context); + mRecentsView = mLauncher.getOverviewPanel(); + } + + @Override + protected boolean isLaunchingFromRecents(@NonNull View v, + @Nullable RemoteAnimationTargetCompat[] targets) { + return mLauncher.getStateManager().getState().overviewUi + && findTaskViewToLaunch(mLauncher, v, targets) != null; + } + + @Override + protected boolean isQuickSwitchInProgress() { + return mRecentsView.getQuickScrubController().isQuickSwitch(); + } + + @Override + protected ActivityOptions getQuickSwitchActivityOptions() { + return ActivityOptions.makeCustomAnimation(mLauncher, R.anim.no_anim, + R.anim.no_anim); + } + + @Override + protected void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v, + @NonNull RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { + RecentsView recentsView = mLauncher.getOverviewPanel(); + boolean skipLauncherChanges = !launcherClosing; + boolean isLaunchingFromQuickscrub = + recentsView.getQuickScrubController().isWaitingForTaskLaunch(); + + TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets); + + int duration = isLaunchingFromQuickscrub + ? RECENTS_QUICKSCRUB_LAUNCH_DURATION + : RECENTS_LAUNCH_DURATION; + + ClipAnimationHelper helper = new ClipAnimationHelper(mLauncher); + anim.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper) + .setDuration(duration)); + + Animator childStateAnimation = null; + // Found a visible recents task that matches the opening app, lets launch the app from there + Animator launcherAnim; + final AnimatorListenerAdapter windowAnimEndListener; + if (launcherClosing) { + launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper); + launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); + launcherAnim.setDuration(duration); + + // Make sure recents gets fixed up by resetting task alphas and scales, etc. + windowAnimEndListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getStateManager().moveToRestState(); + mLauncher.getStateManager().reapplyState(); + } + }; + } else { + AnimatorPlaybackController controller = + mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration); + controller.dispatchOnStart(); + childStateAnimation = controller.getTarget(); + launcherAnim = controller.getAnimationPlayer().setDuration(duration); + windowAnimEndListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getStateManager().goToState(NORMAL, false); + } + }; + } + anim.play(launcherAnim); + + // Set the current animation first, before adding windowAnimEndListener. Setting current + // animation adds some listeners which need to be called before windowAnimEndListener + // (the ordering of listeners matter in this case). + mLauncher.getStateManager().setCurrentAnimation(anim, childStateAnimation); + anim.addListener(windowAnimEndListener); + } + + @Override + protected Runnable composeViewContentAnimator(@NonNull AnimatorSet anim, float[] alphas, + float[] trans) { + RecentsView overview = mLauncher.getOverviewPanel(); + ObjectAnimator alpha = ObjectAnimator.ofFloat(overview, + RecentsView.CONTENT_ALPHA, alphas); + alpha.setDuration(CONTENT_ALPHA_DURATION); + alpha.setInterpolator(LINEAR); + anim.play(alpha); + + ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans); + transY.setInterpolator(AGGRESSIVE_EASE); + transY.setDuration(CONTENT_TRANSLATION_DURATION); + anim.play(transY); + + return mLauncher.getStateManager()::reapplyState; + } +} diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java index de6f7a759..de6f7a759 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/OverviewState.java diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index e0c4e4baa..8d62ab8e1 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -20,6 +20,8 @@ <dimen name="task_thumbnail_half_top_margin">12dp</dimen> <dimen name="task_thumbnail_icon_size">48dp</dimen> <dimen name="task_corner_radius">8dp</dimen> + <!-- For screens without rounded corners --> + <dimen name="task_corner_radius_small">2dp</dimen> <dimen name="recents_page_spacing">10dp</dimen> <dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen> <dimen name="quickscrub_adjacent_visible_width">20dp</dimen> diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index 7c4795694..0c741a140 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -62,8 +62,4 @@ <!-- Annotation shown on an app card in Recents, telling that the app has a usage limit set by the user, and a given time is left for it today [CHAR LIMIT=20] --> <string name="time_left_for_app"><xliff:g id="time" example="7 minutes">%1$s</xliff:g> left today</string> - - <!-- Annotation shown on an app card in Recents, telling that the app is in a group that has a - usage limit set by the user, and a given time is left for the group today [CHAR LIMIT=20] --> - <string name="time_left_for_group"><xliff:g id="time" example="1 hour">%1$s</xliff:g> left for group</string> </resources>
\ No newline at end of file diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java index 08b6bfc6a..c5c5323ec 100644 --- a/quickstep/src/com/android/launcher3/LauncherInitListener.java +++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java @@ -44,8 +44,8 @@ public class LauncherInitListener extends InternalStateHandler implements Activi @Override protected boolean init(Launcher launcher, boolean alreadyOnHome) { if (mRemoteAnimationProvider != null) { - LauncherAppTransitionManagerImpl appTransitionManager = - (LauncherAppTransitionManagerImpl) launcher.getAppTransitionManager(); + QuickstepAppTransitionManagerImpl appTransitionManager = + (QuickstepAppTransitionManagerImpl) launcher.getAppTransitionManager(); // Set a one-time animation provider. After the first call, this will get cleared. // TODO: Probably also check the intended target id. diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index 264ad5ab1..07a5b7202 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -22,7 +22,6 @@ import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS; import static com.android.launcher3.BaseActivity.PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; 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.Utilities.postAsyncCallback; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; @@ -30,8 +29,6 @@ import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS; -import static com.android.quickstep.TaskUtils.findTaskViewToLaunch; -import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; @@ -57,10 +54,12 @@ import android.util.Pair; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.InsettableFrameLayout.LayoutParams; import com.android.launcher3.allapps.AllAppsTransitionController; -import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.graphics.DrawableFactory; @@ -68,12 +67,9 @@ import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.RecentsModel; -import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationTargetSet; -import com.android.quickstep.views.RecentsView; -import com.android.quickstep.views.TaskView; import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; @@ -85,14 +81,15 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. import com.android.systemui.shared.system.WindowManagerWrapper; /** - * Manages the opening and closing app transitions from Launcher. + * {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from + * home and/or all-apps. */ @TargetApi(Build.VERSION_CODES.O) @SuppressWarnings("unused") -public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManager +public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTransitionManager implements OnDeviceProfileChangeListener { - private static final String TAG = "LauncherTransition"; + private static final String TAG = "QuickstepTransition"; /** Duration of status bar animations. */ public static final int STATUS_BAR_TRANSITION_DURATION = 120; @@ -119,10 +116,14 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag private static final int LAUNCHER_RESUME_START_DELAY = 100; private static final int CLOSING_TRANSITION_DURATION_MS = 250; + protected static final int CONTENT_ALPHA_DURATION = 217; + protected static final int CONTENT_TRANSLATION_DURATION = 350; + // Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down. public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f; - private final Launcher mLauncher; + protected final Launcher mLauncher; + private final DragLayer mDragLayer; private final AlphaProperty mDragLayerAlpha; @@ -150,7 +151,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } }; - public LauncherAppTransitionManagerImpl(Context context) { + public QuickstepAppTransitionManagerImpl(Context context) { mLauncher = Launcher.getLauncher(context); mDragLayer = mLauncher.getDragLayer(); mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS); @@ -179,12 +180,9 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag @Override public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) { if (hasControlRemoteAppTransitionPermission()) { - boolean fromRecents = mLauncher.getStateManager().getState().overviewUi - && findTaskViewToLaunch(launcher, v, null) != null; - RecentsView recentsView = mLauncher.getOverviewPanel(); - if (fromRecents && recentsView.getQuickScrubController().isQuickSwitch()) { - return ActivityOptions.makeCustomAnimation(mLauncher, R.anim.no_anim, - R.anim.no_anim); + boolean fromRecents = isLaunchingFromRecents(v, null /* targets */); + if (fromRecents && isQuickSwitchInProgress()) { + return getQuickSwitchActivityOptions(); } RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler, @@ -198,34 +196,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag boolean launcherClosing = launcherIsATargetWithMode(targetCompats, MODE_CLOSING); - if (!composeRecentsLaunchAnimator(v, targetCompats, anim)) { - // Set the state animation first so that any state listeners are called - // before our internal listeners. - mLauncher.getStateManager().setCurrentAnimation(anim); - - Rect windowTargetBounds = getWindowTargetBounds(targetCompats); - boolean isAllOpeningTargetTrs = true; - for (int i = 0; i < targetCompats.length; i++) { - RemoteAnimationTargetCompat target = targetCompats[i]; - if (target.mode == MODE_OPENING) { - isAllOpeningTargetTrs &= target.isTranslucent; - } - if (!isAllOpeningTargetTrs) break; - } - playIconAnimators(anim, v, windowTargetBounds, !isAllOpeningTargetTrs); - if (launcherClosing) { - Pair<AnimatorSet, Runnable> launcherContentAnimator = - getLauncherContentAnimator(true /* isAppOpening */, - new float[] {0, mContentTransY}); - anim.play(launcherContentAnimator.first); - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - launcherContentAnimator.second.run(); - } - }); - } - anim.play(getOpeningWindowAnimators(v, targetCompats, windowTargetBounds)); + if (isLaunchingFromRecents(v, targetCompats)) { + composeRecentsLaunchAnimator(anim, v, targetCompats, launcherClosing); + } else { + composeIconLaunchAnimator(anim, v, targetCompats, launcherClosing); } if (launcherClosing) { @@ -236,6 +210,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } }; + // Note that this duration is a guess as we do not know if the animation will be a + // recents launch or not for sure until we know the opening app targets. int duration = fromRecents ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION; @@ -249,6 +225,83 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } /** + * Whether the launch is a recents app transition and we should do a launch animation + * from the recents view. Note that if the remote animation targets are not provided, this + * may not always be correct as we may resolve the opening app to a task when the animation + * starts. + * + * @param v the view to launch from + * @param targets apps that are opening/closing + * @return true if the app is launching from recents, false if it most likely is not + */ + protected abstract boolean isLaunchingFromRecents(@NonNull View v, + @Nullable RemoteAnimationTargetCompat[] targets); + + /** + * Whether a quick scrub is in progress. + * + * @return true if in progress + */ + protected abstract boolean isQuickSwitchInProgress(); + + /** + * Get activity options for a quick switch launch that include the launch animation. + * + * @return the activity options for a quick switch recents launch + */ + protected abstract ActivityOptions getQuickSwitchActivityOptions(); + + /** + * Composes the animations for a launch from the recents list. + * + * @param anim the animator set to add to + * @param v the launching view + * @param targets the apps that are opening/closing + * @param launcherClosing true if the launcher app is closing + */ + protected abstract void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v, + @NonNull RemoteAnimationTargetCompat[] targets, boolean launcherClosing); + + /** + * Compose the animations for a launch from the app icon. + * + * @param anim the animation to add to + * @param v the launching view with the icon + * @param targets the list of opening/closing apps + * @param launcherClosing true if launcher is closing + */ + private void composeIconLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v, + @NonNull RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { + // Set the state animation first so that any state listeners are called + // before our internal listeners. + mLauncher.getStateManager().setCurrentAnimation(anim); + + Rect windowTargetBounds = getWindowTargetBounds(targets); + boolean isAllOpeningTargetTrs = true; + for (int i = 0; i < targets.length; i++) { + RemoteAnimationTargetCompat target = targets[i]; + if (target.mode == MODE_OPENING) { + isAllOpeningTargetTrs &= target.isTranslucent; + } + if (!isAllOpeningTargetTrs) break; + } + playIconAnimators(anim, v, windowTargetBounds, !isAllOpeningTargetTrs); + if (launcherClosing) { + Pair<AnimatorSet, Runnable> launcherContentAnimator = + getLauncherContentAnimator(true /* isAppOpening */, + new float[] {0, mContentTransY}); + anim.play(launcherContentAnimator.first); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + launcherContentAnimator.second.run(); + } + }); + } + anim.play(getOpeningWindowAnimators(v, targets, windowTargetBounds)); + } + + /** * Return the window bounds of the opening target. * In multiwindow mode, we need to get the final size of the opening app window target to help * figure out where the floating view should animate to. @@ -278,75 +331,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } /** - * Composes the animations for a launch from the recents list if possible. - */ - private boolean composeRecentsLaunchAnimator(View v, - RemoteAnimationTargetCompat[] targets, AnimatorSet target) { - // Ensure recents is actually visible - if (!mLauncher.getStateManager().getState().overviewUi) { - return false; - } - - RecentsView recentsView = mLauncher.getOverviewPanel(); - boolean launcherClosing = launcherIsATargetWithMode(targets, MODE_CLOSING); - boolean skipLauncherChanges = !launcherClosing; - boolean isLaunchingFromQuickscrub = - recentsView.getQuickScrubController().isWaitingForTaskLaunch(); - - TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets); - if (taskView == null) { - return false; - } - - int duration = isLaunchingFromQuickscrub - ? RECENTS_QUICKSCRUB_LAUNCH_DURATION - : RECENTS_LAUNCH_DURATION; - - ClipAnimationHelper helper = new ClipAnimationHelper(mLauncher); - target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper) - .setDuration(duration)); - - Animator childStateAnimation = null; - // Found a visible recents task that matches the opening app, lets launch the app from there - Animator launcherAnim; - final AnimatorListenerAdapter windowAnimEndListener; - if (launcherClosing) { - launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper); - launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); - launcherAnim.setDuration(duration); - - // Make sure recents gets fixed up by resetting task alphas and scales, etc. - windowAnimEndListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mLauncher.getStateManager().moveToRestState(); - mLauncher.getStateManager().reapplyState(); - } - }; - } else { - AnimatorPlaybackController controller = - mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration); - controller.dispatchOnStart(); - childStateAnimation = controller.getTarget(); - launcherAnim = controller.getAnimationPlayer().setDuration(duration); - windowAnimEndListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mLauncher.getStateManager().goToState(NORMAL, false); - } - }; - } - target.play(launcherAnim); - - // Set the current animation first, before adding windowAnimEndListener. Setting current - // animation adds some listeners which need to be called before windowAnimEndListener - // (the ordering of listeners matter in this case). - mLauncher.getStateManager().setCurrentAnimation(target, childStateAnimation); - target.addListener(windowAnimEndListener); - return true; - } - - /** * Content is everything on screen except the background and the floating view (if any). * * @param isAppOpening True when this is called when an app is opening. @@ -371,7 +355,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag appsView.setTranslationY(trans[0]); ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas); - alpha.setDuration(217); + alpha.setDuration(CONTENT_ALPHA_DURATION); alpha.setInterpolator(LINEAR); appsView.setLayerType(View.LAYER_TYPE_HARDWARE, null); alpha.addListener(new AnimatorListenerAdapter() { @@ -382,7 +366,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag }); ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans); transY.setInterpolator(AGGRESSIVE_EASE); - transY.setDuration(350); + transY.setDuration(CONTENT_TRANSLATION_DURATION); launcherAnimator.play(alpha); launcherAnimator.play(transY); @@ -396,32 +380,19 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); launcherAnimator.play(ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, allAppsController.getProgress(), ALL_APPS_PROGRESS_OFF_SCREEN)); - - RecentsView overview = mLauncher.getOverviewPanel(); - ObjectAnimator alpha = ObjectAnimator.ofFloat(overview, - RecentsView.CONTENT_ALPHA, alphas); - alpha.setDuration(217); - alpha.setInterpolator(LINEAR); - launcherAnimator.play(alpha); - - ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans); - transY.setInterpolator(AGGRESSIVE_EASE); - transY.setDuration(350); - launcherAnimator.play(transY); - - endListener = mLauncher.getStateManager()::reapplyState; + endListener = composeViewContentAnimator(launcherAnimator, alphas, trans); } else { mDragLayerAlpha.setValue(alphas[0]); ObjectAnimator alpha = ObjectAnimator.ofFloat(mDragLayerAlpha, MultiValueAlpha.VALUE, alphas); - alpha.setDuration(217); + alpha.setDuration(CONTENT_ALPHA_DURATION); alpha.setInterpolator(LINEAR); launcherAnimator.play(alpha); mDragLayer.setTranslationY(trans[0]); ObjectAnimator transY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, trans); transY.setInterpolator(AGGRESSIVE_EASE); - transY.setDuration(350); + transY.setDuration(CONTENT_TRANSLATION_DURATION); launcherAnimator.play(transY); mDragLayer.getScrim().hideSysUiScrim(true); @@ -435,6 +406,17 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } /** + * Compose recents view alpha and translation Y animation when launcher opens/closes apps. + * + * @param anim the animator set to add to + * @param alphas the alphas to animate to over time + * @param trans the translation Y values to animator to over time + * @return listener to run when the animation ends + */ + protected abstract Runnable composeViewContentAnimator(@NonNull AnimatorSet anim, + float[] alphas, float[] trans); + + /** * Animators for the "floating view" of the view used to launch the target. */ private void playIconAnimators(AnimatorSet appOpenAnimator, View v, Rect windowTargetBounds, @@ -633,9 +615,12 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag // Animate window corner radius from 100% to windowCornerRadius. float windowCornerRadius = RecentsModel.INSTANCE.get(mLauncher) .getWindowCornerRadius(); - float circleRadius = iconWidth / 2f; - float windowRadius = Utilities.mapRange(easePercent, circleRadius, - windowCornerRadius); + float windowRadius = 0; + if (RecentsModel.INSTANCE.get(mLauncher).supportsRoundedCornersOnWindows()) { + float circleRadius = iconWidth / 2f; + windowRadius = Utilities.mapRange(easePercent, circleRadius, + windowCornerRadius); + } // Animate the window crop so that it starts off as a square, and then reveals // horizontally. diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index a9b251609..d295ac5c5 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -37,10 +37,10 @@ import android.util.Base64; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherAppTransitionManagerImpl; import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager; import com.android.launcher3.LauncherStateManager.StateHandler; +import com.android.launcher3.QuickstepAppTransitionManagerImpl; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.TouchController; @@ -203,8 +203,8 @@ public class UiFactory { public static void useFadeOutAnimationForLauncherStart(Launcher launcher, CancellationSignal cancellationSignal) { - LauncherAppTransitionManagerImpl appTransitionManager = - (LauncherAppTransitionManagerImpl) launcher.getAppTransitionManager(); + QuickstepAppTransitionManagerImpl appTransitionManager = + (QuickstepAppTransitionManagerImpl) launcher.getAppTransitionManager(); appTransitionManager.setRemoteAnimationProvider((targets) -> { // On the first call clear the reference. diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index deedd324a..89c7abadb 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -18,9 +18,11 @@ package com.android.quickstep; import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY; +import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; +import static com.android.launcher3.QuickstepAppTransitionManagerImpl + .STATUS_BAR_TRANSITION_DURATION; +import static com.android.launcher3.QuickstepAppTransitionManagerImpl + .STATUS_BAR_TRANSITION_PRE_DELAY; import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index 442b106fa..e61c00af7 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -66,6 +66,7 @@ public class RecentsModel extends TaskStackChangeListener { private final TaskThumbnailCache mThumbnailCache; private float mWindowCornerRadius = -1; + private Boolean mSupportsRoundedCornersOnWindows; private RecentsModel(Context context) { mContext = context; @@ -199,6 +200,26 @@ public class RecentsModel extends TaskStackChangeListener { return mWindowCornerRadius; } + public boolean supportsRoundedCornersOnWindows() { + if (mSupportsRoundedCornersOnWindows == null) { + if (mSystemUiProxy != null) { + try { + mSupportsRoundedCornersOnWindows = + mSystemUiProxy.supportsRoundedCornersOnWindows(); + } catch (RemoteException e) { + Log.w(TAG, "Connection to ISystemUIProxy was lost, ignoring window corner " + + "radius"); + return false; + } + } else { + Log.w(TAG, "ISystemUIProxy is null, ignoring window corner radius"); + return false; + } + } + + return mSupportsRoundedCornersOnWindows; + } + public void onTrimMemory(int level) { if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { mThumbnailCache.getHighResLoadingState().setVisible(false); diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java index 84033cbd6..31de68395 100644 --- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -91,6 +91,8 @@ public class ClipAnimationHelper { private final float mWindowCornerRadius; // Corner radius of windows when they're in overview mode. private final float mTaskCornerRadius; + // If windows can have real time rounded corners. + private final boolean mSupportsRoundedCornersOnWindows; // Corner radius currently applied to transformed window. private float mCurrentCornerRadius; @@ -107,8 +109,12 @@ public class ClipAnimationHelper { (t, a1) -> a1; public ClipAnimationHelper(Context context) { - mTaskCornerRadius = context.getResources().getDimension(R.dimen.task_corner_radius); - mWindowCornerRadius = RecentsModel.INSTANCE.get(context).getWindowCornerRadius(); + mWindowCornerRadius = RecentsModel.INSTANCE.get(context).getWindowCornerRadius(); + mSupportsRoundedCornersOnWindows = RecentsModel.INSTANCE.get(context) + .supportsRoundedCornersOnWindows(); + int taskCornerRadiusRes = mSupportsRoundedCornersOnWindows ? + R.dimen.task_corner_radius : R.dimen.task_corner_radius_small; + mTaskCornerRadius = context.getResources().getDimension(taskCornerRadiusRes); } private void updateSourceStack(RemoteAnimationTargetCompat target) { @@ -197,9 +203,10 @@ public class ClipAnimationHelper { mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL); mTmpMatrix.postTranslate(app.position.x, app.position.y); mClipRectF.roundOut(crop); - cornerRadius = Utilities.mapRange(params.progress, mWindowCornerRadius, - mTaskCornerRadius); - mCurrentCornerRadius = cornerRadius; + if (mSupportsRoundedCornersOnWindows) { + cornerRadius = Utilities.mapRange(params.progress, mWindowCornerRadius, + mTaskCornerRadius); + } } alpha = mTaskAlphaCallback.apply(app, params.targetAlpha); } else if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java index aafd725cb..9ad750b1b 100644 --- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java +++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java @@ -77,7 +77,6 @@ public final class DigitalWellBeingToast extends LinearLayout { Utilities.THREAD_POOL_EXECUTOR.execute(() -> { long appUsageLimitTimeMs = -1; long appRemainingTimeMs = -1; - boolean isGroupLimit = true; try { final Method getAppUsageLimit = LauncherApps.class.getMethod( @@ -95,8 +94,6 @@ public final class DigitalWellBeingToast extends LinearLayout { invoke(usageLimit); appRemainingTimeMs = (long) appUsageLimitClass.getMethod("getUsageRemaining"). invoke(usageLimit); - isGroupLimit = (boolean) appUsageLimitClass.getMethod("isGroupLimit"). - invoke(usageLimit); } } catch (Exception e) { // Do nothing @@ -104,14 +101,13 @@ public final class DigitalWellBeingToast extends LinearLayout { final long appUsageLimitTimeMsFinal = appUsageLimitTimeMs; final long appRemainingTimeMsFinal = appRemainingTimeMs; - final boolean isGroupLimitFinal = isGroupLimit; post(() -> { if (appUsageLimitTimeMsFinal < 0) { setVisibility(GONE); } else { setVisibility(VISIBLE); - mText.setText(getText(appRemainingTimeMsFinal, isGroupLimitFinal)); + mText.setText(getText(appRemainingTimeMsFinal)); mImage.setImageResource(appRemainingTimeMsFinal > 0 ? R.drawable.hourglass_top : R.drawable.hourglass_bottom); } @@ -119,9 +115,7 @@ public final class DigitalWellBeingToast extends LinearLayout { callback.call( appUsageLimitTimeMsFinal >= 0 && appRemainingTimeMsFinal <= 0 ? 0 : 1, getContentDescriptionForTask( - task, appUsageLimitTimeMsFinal, - appRemainingTimeMsFinal, - isGroupLimitFinal)); + task, appUsageLimitTimeMsFinal, appRemainingTimeMsFinal)); }); }); } @@ -185,12 +179,12 @@ public final class DigitalWellBeingToast extends LinearLayout { duration, FormatWidth.NARROW, R.string.shorter_duration_less_than_one_minute); } - private String getText(long remainingTime, boolean isGroupLimit) { + private String getText(long remainingTime) { final Resources resources = getResources(); return (remainingTime <= 0) ? resources.getString(R.string.app_in_grayscale) : resources.getString( - isGroupLimit ? R.string.time_left_for_group : R.string.time_left_for_app, + R.string.time_left_for_app, getShorterReadableDuration(Duration.ofMillis(remainingTime))); } @@ -214,12 +208,12 @@ public final class DigitalWellBeingToast extends LinearLayout { } private String getContentDescriptionForTask( - Task task, long appUsageLimitTimeMs, long appRemainingTimeMs, boolean isGroupLimit) { + Task task, long appUsageLimitTimeMs, long appRemainingTimeMs) { return appUsageLimitTimeMs >= 0 ? getResources().getString( R.string.task_contents_description_with_remaining_time, task.titleDescription, - getText(appRemainingTimeMs, isGroupLimit)) : + getText(appRemainingTimeMs)) : task.titleDescription; } } diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 722c721f9..f8eced00a 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -16,9 +16,9 @@ package com.android.quickstep.views; import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW; -import static com.android.launcher3.LauncherAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN; import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA; import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; |