Merge "[Toast] Introduce SysUI's animation library to the transition manager." into tm-qpr-dev am: f70e2f0a95

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/20836638

Change-Id: Ic4f5610fe4c04a5b876356d9912bf8f9eabc35b2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Luca Zuccarini
2023-01-30 14:51:12 +00:00
committed by Automerger Merge Worker
7 changed files with 162 additions and 7 deletions

View File

@@ -89,6 +89,7 @@ import android.provider.Settings;
import android.util.Pair;
import android.util.Size;
import android.view.CrossWindowBlurListeners;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationTarget;
@@ -114,6 +115,7 @@ import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
@@ -143,6 +145,9 @@ import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.WorkspaceRevealAnim;
import com.android.quickstep.views.FloatingWidgetView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
import com.android.systemui.animation.RemoteAnimationDelegate;
import com.android.systemui.shared.system.BlurUtils;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -222,7 +227,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
private RemoteAnimationProvider mRemoteAnimationProvider;
// Strong refs to runners which are cleared when the launcher activity is destroyed
private RemoteAnimationFactory mWallpaperOpenRunner;
private RemoteAnimationFactory mAppLaunchRunner;
private RemoteAnimationFactory mKeyguardGoingAwayRunner;
private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
@@ -291,9 +295,18 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
RunnableList onEndCallback = new RunnableList();
mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);
RemoteAnimationFactory delegateRunner = new AppLaunchAnimationRunner(v, onEndCallback);
ItemInfo tag = (ItemInfo) v.getTag();
if (tag != null && tag.shouldUseBackgroundAnimation()) {
ContainerAnimationRunner containerAnimationRunner =
ContainerAnimationRunner.from(v, mStartingWindowListener);
if (containerAnimationRunner != null) {
delegateRunner = containerAnimationRunner;
}
}
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(
mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */);
mHandler, delegateRunner, true /* startAtFrontOfQueue */);
// 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.
@@ -1160,7 +1173,6 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
// Also clear strong references to the runners registered with the remote animation
// definition so we don't have to wait for the system gc
mWallpaperOpenRunner = null;
mAppLaunchRunner = null;
mKeyguardGoingAwayRunner = null;
}
}
@@ -1754,6 +1766,79 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
}
}
/** Remote animation runner to launch an app using System UI's animation library. */
private static class ContainerAnimationRunner implements RemoteAnimationFactory {
/** The delegate runner that handles the actual animation. */
private final RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> mDelegate;
private ContainerAnimationRunner(
RemoteAnimationDelegate<IRemoteAnimationFinishedCallback> delegate) {
mDelegate = delegate;
}
@Nullable
private static ContainerAnimationRunner from(
View v, StartingWindowListener startingWindowListener) {
View viewToUse = findViewWithBackground(v);
if (viewToUse == null) {
viewToUse = v;
}
// TODO(b/265134143): create a CUJ type for interaction jank monitoring.
ActivityLaunchAnimator.Controller controllerDelegate =
ActivityLaunchAnimator.Controller.fromView(viewToUse, null /* cujType */);
if (controllerDelegate == null) {
return null;
}
// This wrapper allows us to override the default value, telling the controller that the
// current window is below the animating window.
ActivityLaunchAnimator.Controller controller =
new DelegateLaunchAnimatorController(controllerDelegate) {
@Override
public boolean isBelowAnimatingWindow() {
return true;
}
};
ActivityLaunchAnimator.Callback callback = task -> ColorUtils.setAlphaComponent(
startingWindowListener.getBackgroundColor(), 255);
return new ContainerAnimationRunner(
new ActivityLaunchAnimator.AnimationDelegate(controller, callback));
}
/** Finds the closest parent of [view] (inclusive) with a background drawable. */
@Nullable
private static View findViewWithBackground(View view) {
View current = view;
while (current.getBackground() == null) {
if (!(current.getParent() instanceof View)) {
return null;
}
current = (View) view.getParent();
}
return current;
}
@Override
public void onAnimationStart(int transit, RemoteAnimationTarget[] appTargets,
RemoteAnimationTarget[] wallpaperTargets, RemoteAnimationTarget[] nonAppTargets,
LauncherAnimationRunner.AnimationResult result) {
mDelegate.onAnimationStart(
transit, appTargets, wallpaperTargets, nonAppTargets, result);
}
@Override
public void onAnimationCancelled(boolean isKeyguardOccluded) {
mDelegate.onAnimationCancelled(isKeyguardOccluded);
}
}
/**
* Class that holds all the variables for the app open animation.
*/
@@ -1822,8 +1907,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
}
}
private static class StartingWindowListener extends IStartingWindowListener.Stub {
private class StartingWindowListener extends IStartingWindowListener.Stub {
private QuickstepTransitionManager mTransitionManager;
private int mBackgroundColor;
public void setTransitionManager(QuickstepTransitionManager transitionManager) {
mTransitionManager = transitionManager;
@@ -1832,6 +1918,13 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
@Override
public void onTaskLaunching(int taskId, int supportedType, int color) {
mTransitionManager.mTaskStartParams.put(taskId, Pair.create(supportedType, color));
mBackgroundColor = color;
}
public int getBackgroundColor() {
return mBackgroundColor == Color.TRANSPARENT
? mLauncher.getScrimView().getBackgroundColor()
: mBackgroundColor;
}
}

View File

@@ -29,6 +29,20 @@ import com.android.launcher3.model.data.ItemInfo;
*/
public class LauncherSettings {
/**
* Types of animations.
*/
public static final class Animation {
/**
* The default animation for a given view/item info type.
*/
public static final int DEFAULT = 0;
/**
* An animation using the view's background.
*/
public static final int VIEW_BACKGROUND = 1;
}
/**
* Favorites.
*/

View File

@@ -272,7 +272,7 @@ public final class FeatureFlags {
public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = new DeviceFlag(
"ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", false,
"Enable option to launch search results using the new standardized transitions");
"Enable option to launch search results using the new view container transitions");
public static final BooleanFlag TWO_PREDICTED_ROWS_ALL_APPS_SEARCH = new DeviceFlag(
"TWO_PREDICTED_ROWS_ALL_APPS_SEARCH", false,

View File

@@ -47,8 +47,10 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Animation;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.AllAppsContainer;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
@@ -93,6 +95,12 @@ public class ItemInfo {
*/
public int itemType;
/**
* One of {@link Animation#DEFAULT},
* {@link Animation#VIEW_BACKGROUND}.
*/
public int animationType = Animation.DEFAULT;
/**
* The id of the container that holds this item. For the desktop, this will be
* {@link Favorites#CONTAINER_DESKTOP}. For the all applications folder it
@@ -185,6 +193,7 @@ public class ItemInfo {
rank = info.rank;
screenId = info.screenId;
itemType = info.itemType;
animationType = info.animationType;
container = info.container;
user = info.user;
contentDescription = info.contentDescription;
@@ -297,6 +306,15 @@ public class ItemInfo {
return container == CONTAINER_HOTSEAT_PREDICTION || container == CONTAINER_PREDICTION;
}
/**
* Returns whether this item should use the background animation.
*/
public boolean shouldUseBackgroundAnimation() {
return animationType == LauncherSettings.Animation.VIEW_BACKGROUND
&& FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()
&& FeatureFlags.ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION.get();
}
/**
* Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
*/

View File

@@ -343,7 +343,8 @@ public class ItemClickHandler {
return;
}
}
if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
if (v != null && launcher.supportsAdaptiveIconAnimation(v)
&& !item.shouldUseBackgroundAnimation()) {
// Preload the icon to reduce latency b/w swapping the floating view with the original.
FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
}

View File

@@ -23,6 +23,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.ContextWrapper;
@@ -45,6 +46,7 @@ import android.view.WindowInsetsController;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.BubbleTextView;
@@ -277,6 +279,29 @@ public interface ActivityContext {
}
}
/**
* Sends a pending intent animating from a view.
*
* @param v View to animate.
* @param intent The pending intent being launched.
* @param item Item associated with the view.
* @return {@code true} if the intent is sent successfully.
*/
default boolean sendPendingIntentWithAnimation(
@NonNull View v, PendingIntent intent, @Nullable ItemInfo item) {
Bundle optsBundle = getActivityLaunchOptions(v, item).toBundle();
try {
intent.send(null, 0, null, null, null, null, optsBundle);
return true;
} catch (PendingIntent.CanceledException e) {
Toast.makeText(v.getContext(),
v.getContext().getResources().getText(R.string.shortcut_not_available),
Toast.LENGTH_SHORT).show();
}
return false;
}
/**
* Safely starts an activity.
*

View File

@@ -77,6 +77,10 @@ public class ScrimView extends View implements Insettable {
super.setBackgroundColor(color);
}
public int getBackgroundColor() {
return mBackgroundColor;
}
@Override
public void onVisibilityAggregated(boolean isVisible) {
super.onVisibilityAggregated(isVisible);