Merge "Adding support for listening for app launch animation completion" into sc-dev

This commit is contained in:
Sunny Goyal
2021-03-11 21:36:43 +00:00
committed by Android (Google) Code Review
31 changed files with 397 additions and 480 deletions
-2
View File
@@ -17,8 +17,6 @@
<!-- 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>
<string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
<string name="app_launch_tracker_class" translatable="false">com.android.launcher3.appprediction.PredictionAppTracker</string>
@@ -25,7 +25,6 @@ import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SY
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
@@ -47,6 +46,7 @@ import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarController;
import com.android.launcher3.taskbar.TaskbarStateHandler;
import com.android.launcher3.uioverrides.RecentsViewStateController;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.RecentsModel;
@@ -73,6 +73,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
implements NavigationModeChangeListener {
private DepthController mDepthController = new DepthController(this);
private QuickstepTransitionManager mAppTransitionManager;
/**
* Reusable command for applying the back button alpha on the background thread.
@@ -91,6 +92,8 @@ public abstract class BaseQuickstepLauncher extends Launcher
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAppTransitionManager = new QuickstepTransitionManager(this);
mAppTransitionManager.registerRemoteAnimations();
SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
addMultiWindowModeChangedListener(mDepthController);
@@ -98,8 +101,9 @@ public abstract class BaseQuickstepLauncher extends Launcher
@Override
public void onDestroy() {
SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
mAppTransitionManager.onActivityDestroyed();
SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
if (mTaskbarController != null) {
mTaskbarController.cleanup();
}
@@ -107,6 +111,10 @@ public abstract class BaseQuickstepLauncher extends Launcher
super.onDestroy();
}
public QuickstepTransitionManager getAppTransitionManager() {
return mAppTransitionManager;
}
@Override
public void onNavigationModeChanged(Mode newMode) {
getDragLayer().recreateControllers();
@@ -270,6 +278,12 @@ public abstract class BaseQuickstepLauncher extends Launcher
return mTaskbarController != null && mTaskbarController.isViewInTaskbar(v);
}
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
&& FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get()
&& !isViewInTaskbar(clickedView);
}
@Override
public DragOptions getDefaultWorkspaceDragOptions() {
if (mNextWorkspaceDragOptions != null) {
@@ -286,8 +300,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
@Override
public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
QuickstepAppTransitionManagerImpl appTransitionManager =
(QuickstepAppTransitionManagerImpl) getAppTransitionManager();
QuickstepTransitionManager appTransitionManager = getAppTransitionManager();
appTransitionManager.setRemoteAnimationProvider(new RemoteAnimationProvider() {
@Override
public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
@@ -379,10 +392,14 @@ public abstract class BaseQuickstepLauncher extends Launcher
}
@Override
public ActivityOptions getActivityLaunchOptions(View v) {
ActivityOptions activityOptions = super.getActivityLaunchOptions(v);
if (activityOptions != null && mLastTouchUpTime > 0) {
ActivityOptionsCompat.setLauncherSourceInfo(activityOptions, mLastTouchUpTime);
public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
ActivityOptionsWrapper activityOptions =
mAppTransitionManager.hasControlRemoteAppTransitionPermission()
? mAppTransitionManager.getActivityLaunchOptions(this, v)
: super.getActivityLaunchOptions(v);
if (mLastTouchUpTime > 0) {
ActivityOptionsCompat.setLauncherSourceInfo(
activityOptions.options, mLastTouchUpTime);
}
return activityOptions;
}
@@ -17,6 +17,7 @@ package com.android.launcher3;
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
@@ -29,6 +30,7 @@ import android.os.Build;
import android.os.Handler;
import androidx.annotation.BinderThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
@@ -37,8 +39,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@TargetApi(Build.VERSION_CODES.P)
public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
private static final String TAG = "LauncherAnimationRunner";
private final Handler mHandler;
private final boolean mStartAtFrontOfQueue;
private AnimationResult mAnimationResult;
@@ -66,10 +66,7 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
Runnable runnable) {
Runnable r = () -> {
finishExistingAnimation();
mAnimationResult = new AnimationResult(() -> {
UI_HELPER_EXECUTOR.execute(runnable);
mAnimationResult = null;
});
mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);
onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets,
mAnimationResult);
};
@@ -126,37 +123,60 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
public static final class AnimationResult {
private final Runnable mFinishRunnable;
private final Runnable mSyncFinishRunnable;
private final Runnable mASyncFinishRunnable;
private AnimatorSet mAnimator;
private Runnable mOnCompleteCallback;
private boolean mFinished = false;
private boolean mInitialized = false;
private AnimationResult(Runnable finishRunnable) {
mFinishRunnable = finishRunnable;
private AnimationResult(Runnable syncFinishRunnable, Runnable asyncFinishRunnable) {
mSyncFinishRunnable = syncFinishRunnable;
mASyncFinishRunnable = asyncFinishRunnable;
}
@UiThread
private void finish() {
if (!mFinished) {
mFinishRunnable.run();
mSyncFinishRunnable.run();
UI_HELPER_EXECUTOR.execute(() -> {
mASyncFinishRunnable.run();
if (mOnCompleteCallback != null) {
MAIN_EXECUTOR.execute(mOnCompleteCallback);
}
});
mFinished = true;
}
}
@UiThread
public void setAnimation(AnimatorSet animation, Context context) {
setAnimation(animation, context, null);
}
/**
* Sets the animation to play for this app launch
*/
@UiThread
public void setAnimation(AnimatorSet animation, Context context,
@Nullable Runnable onCompleteCallback) {
if (mInitialized) {
throw new IllegalStateException("Animation already initialized");
}
mInitialized = true;
mAnimator = animation;
mOnCompleteCallback = onCompleteCallback;
if (mAnimator == null) {
finish();
} else if (mFinished) {
// Animation callback was already finished, skip the animation.
mAnimator.start();
mAnimator.end();
if (mOnCompleteCallback != null) {
mOnCompleteCallback.run();
}
} else {
// Start the animation
mAnimator.addListener(new AnimatorListenerAdapter() {
@@ -1,83 +0,0 @@
/*
* 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.anim.Interpolators.AGGRESSIVE_EASE;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* A {@link QuickstepAppTransitionManagerImpl} that also implements recents transitions from
* {@link RecentsView}.
*/
public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransitionManagerImpl {
public LauncherAppTransitionManagerImpl(Context context) {
super(context);
}
@Override
protected boolean isLaunchingFromRecents(@NonNull View v,
@Nullable RemoteAnimationTargetCompat[] targets) {
return mLauncher.getStateManager().getState().overviewUi
&& findTaskViewToLaunch(mLauncher.getOverviewPanel(), v, targets) != null;
}
@Override
protected void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v,
@NonNull RemoteAnimationTargetCompat[] appTargets,
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets, boolean launcherClosing) {
TaskViewUtils.composeRecentsLaunchAnimator(anim, v, appTargets, wallpaperTargets,
launcherClosing, mLauncher.getStateManager(), mLauncher.getOverviewPanel(),
mLauncher.getDepthController());
}
@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);
overview.setFreezeViewVisibility(true);
ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans);
transY.setInterpolator(AGGRESSIVE_EASE);
transY.setDuration(CONTENT_TRANSLATION_DURATION);
anim.play(transY);
return () -> {
overview.setFreezeViewVisibility(false);
overview.setTranslationY(0);
mLauncher.getStateManager().reapplyState();
};
}
}
@@ -46,8 +46,8 @@ public class LauncherInitListener extends ActivityInitListener<Launcher> {
@Override
public boolean handleInit(Launcher launcher, boolean alreadyOnHome) {
if (mRemoteAnimationProvider != null) {
QuickstepAppTransitionManagerImpl appTransitionManager =
(QuickstepAppTransitionManagerImpl) launcher.getAppTransitionManager();
QuickstepTransitionManager appTransitionManager =
((BaseQuickstepLauncher) launcher).getAppTransitionManager();
// Set a one-time animation provider. After the first call, this will get cleared.
// TODO: Probably also check the intended target id.
@@ -37,6 +37,7 @@ import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVIT
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
@@ -47,7 +48,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -69,20 +69,23 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.IStartingWindowListener;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityOptionsCompat;
@@ -99,12 +102,9 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.LinkedHashMap;
/**
* {@link LauncherAppTransitionManager} with Quickstep-specific app transitions for launching from
* home and/or all-apps. Not used for 3p launchers.
* Manages the opening and closing app transitions from Launcher
*/
@SuppressWarnings("unused")
public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTransitionManager
implements OnDeviceProfileChangeListener {
public class QuickstepTransitionManager implements OnDeviceProfileChangeListener {
private static final String TAG = "QuickstepTransition";
@@ -115,8 +115,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
public static final int STATUS_BAR_TRANSITION_DURATION = 120;
/**
* Since our animations decelerate heavily when finishing, we want to start status bar animations
* x ms before the ending.
* Since our animations decelerate heavily when finishing, we want to start status bar
* animations x ms before the ending.
*/
public static final int STATUS_BAR_TRANSITION_PRE_DELAY = 96;
@@ -191,7 +191,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
// Will never be larger than MAX_NUM_TASKS
private LinkedHashMap<Integer, Integer> mTypeForTaskId;
public QuickstepAppTransitionManagerImpl(Context context) {
public QuickstepTransitionManager(Context context) {
mLauncher = Launcher.cast(Launcher.getLauncher(context));
mDragLayer = mLauncher.getDragLayer();
mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS);
@@ -229,37 +229,29 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
mDeviceProfile = dp;
}
@Override
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return hasControlRemoteAppTransitionPermission()
&& FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get()
&& !mLauncher.isViewInTaskbar(clickedView);
}
/**
* @return ActivityOptions with remote animations that controls how the window of the opening
* targets are displayed.
*/
@Override
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
if (hasControlRemoteAppTransitionPermission()) {
boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
mAppLaunchRunner = new AppLaunchAnimationRunner(mHandler, v);
RemoteAnimationRunnerCompat runner = new WrappedLauncherAnimationRunner<>(
mAppLaunchRunner, true /* startAtFrontOfQueue */);
public ActivityOptionsWrapper getActivityLaunchOptions(Launcher launcher, View v) {
boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
RunnableList onEndCallback = new RunnableList();
mAppLaunchRunner = new AppLaunchAnimationRunner(mHandler, v, onEndCallback);
RemoteAnimationRunnerCompat runner = new WrappedLauncherAnimationRunner<>(
mHandler, mAppLaunchRunner, 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.
long duration = fromRecents
? RECENTS_LAUNCH_DURATION
: APP_LAUNCH_DURATION;
// 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.
long duration = fromRecents
? RECENTS_LAUNCH_DURATION
: APP_LAUNCH_DURATION;
long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
- STATUS_BAR_TRANSITION_PRE_DELAY;
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
runner, duration, statusBarTransitionDelay));
}
return super.getActivityLaunchOptions(launcher, v);
long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
- STATUS_BAR_TRANSITION_PRE_DELAY;
RemoteAnimationAdapterCompat adapterCompat =
new RemoteAnimationAdapterCompat(runner, duration, statusBarTransitionDelay);
return new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat), onEndCallback);
}
/**
@@ -272,8 +264,11 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
* @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);
protected boolean isLaunchingFromRecents(@NonNull View v,
@Nullable RemoteAnimationTargetCompat[] targets) {
return mLauncher.getStateManager().getState().overviewUi
&& findTaskViewToLaunch(mLauncher.getOverviewPanel(), v, targets) != null;
}
/**
* Composes the animations for a launch from the recents list.
@@ -283,9 +278,13 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
* @param appTargets 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,
protected void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v,
@NonNull RemoteAnimationTargetCompat[] appTargets,
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets, boolean launcherClosing);
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets, boolean launcherClosing) {
TaskViewUtils.composeRecentsLaunchAnimator(anim, v, appTargets, wallpaperTargets,
launcherClosing, mLauncher.getStateManager(), mLauncher.getOverviewPanel(),
mLauncher.getDepthController());
}
private boolean areAllTargetsTranslucent(@NonNull RemoteAnimationTargetCompat[] targets) {
boolean isAllOpeningTargetTrs = true;
@@ -483,8 +482,27 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
* @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);
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);
overview.setFreezeViewVisibility(true);
ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans);
transY.setInterpolator(AGGRESSIVE_EASE);
transY.setDuration(CONTENT_TRANSLATION_DURATION);
anim.play(transY);
return () -> {
overview.setFreezeViewVisibility(false);
overview.setTranslationY(0);
mLauncher.getStateManager().reapplyState();
};
}
/**
* @return Animator that controls the window of the opening targets from app icons.
@@ -686,7 +704,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
/**
* Registers remote animations used when closing apps to home screen.
*/
@Override
public void registerRemoteAnimations() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
@@ -698,7 +715,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
new RemoteAnimationAdapterCompat(
new WrappedLauncherAnimationRunner<>(mWallpaperOpenRunner,
new WrappedLauncherAnimationRunner<>(mHandler, mWallpaperOpenRunner,
false /* startAtFrontOfQueue */),
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
@@ -707,7 +724,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
definition.addRemoteAnimation(
WindowManagerWrapper.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
new RemoteAnimationAdapterCompat(
new WrappedLauncherAnimationRunner<>(mKeyguardGoingAwayRunner,
new WrappedLauncherAnimationRunner<>(
mHandler, mKeyguardGoingAwayRunner,
true /* startAtFrontOfQueue */),
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
}
@@ -719,7 +737,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
/**
* Registers remote animations used when closing apps to home screen.
*/
@Override
public void registerRemoteTransitions() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
@@ -727,26 +744,20 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
if (hasControlRemoteAppTransitionPermission()) {
mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
mLauncherOpenTransition = RemoteAnimationAdapterCompat.buildRemoteTransition(
new WrappedLauncherAnimationRunner<>(mWallpaperOpenTransitionRunner,
new WrappedLauncherAnimationRunner<>(mHandler, mWallpaperOpenTransitionRunner,
false /* startAtFrontOfQueue */));
mLauncherOpenTransition.addHomeOpenCheck();
SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
}
}
@Override
public void onActivityDestroyed() {
super.onActivityDestroyed();
unregisterRemoteAnimations();
unregisterRemoteTransitions();
SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null);
}
/**
* Unregisters all remote animations.
*/
@Override
public void unregisterRemoteAnimations() {
private void unregisterRemoteAnimations() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
@@ -761,8 +772,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
}
}
@Override
public void unregisterRemoteTransitions() {
private void unregisterRemoteTransitions() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
@@ -883,7 +893,10 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
&& ENABLE_SHELL_STARTING_SURFACE;
}
private boolean hasControlRemoteAppTransitionPermission() {
/**
* Returns true if we have permission to control remote app transisions
*/
public boolean hasControlRemoteAppTransitionPermission() {
return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION)
== PackageManager.PERMISSION_GRANTED;
}
@@ -922,11 +935,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
mFromUnlock = fromUnlock;
}
@Override
public Handler getHandler() {
return mHandler;
}
@Override
public void onCreateAnimation(int transit,
RemoteAnimationTargetCompat[] appTargets,
@@ -1017,15 +1025,12 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
private final Handler mHandler;
private final View mV;
private final RunnableList mOnEndCallback;
AppLaunchAnimationRunner(Handler handler, View v) {
AppLaunchAnimationRunner(Handler handler, View v, RunnableList onEndCallback) {
mHandler = handler;
mV = v;
}
@Override
public Handler getHandler() {
return mHandler;
mOnEndCallback = onEndCallback;
}
@Override
@@ -1060,7 +1065,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
anim.addListener(mForceInvisibleListener);
}
result.setAnimation(anim, mLauncher);
result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy);
}
}
@@ -16,8 +16,6 @@
package com.android.launcher3;
import android.os.Handler;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
@@ -25,7 +23,7 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
* implementation.
*/
public interface WrappedAnimationRunnerImpl {
Handler getHandler();
void onCreateAnimation(int transit,
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
@@ -16,6 +16,8 @@
package com.android.launcher3;
import android.os.Handler;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.lang.ref.WeakReference;
@@ -40,8 +42,9 @@ public class WrappedLauncherAnimationRunner<R extends WrappedAnimationRunnerImpl
extends LauncherAnimationRunner {
private WeakReference<R> mImpl;
public WrappedLauncherAnimationRunner(R animationRunnerImpl, boolean startAtFrontOfQueue) {
super(animationRunnerImpl.getHandler(), startAtFrontOfQueue);
public WrappedLauncherAnimationRunner(
Handler handler, R animationRunnerImpl, boolean startAtFrontOfQueue) {
super(handler, startAtFrontOfQueue);
mImpl = new WeakReference<>(animationRunnerImpl);
}
@@ -41,7 +41,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepAppTransitionManagerImpl;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.folder.Folder;
@@ -299,7 +299,7 @@ public class TaskbarController {
* Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
*/
public void onLauncherResumedOrPaused(boolean isResumed) {
long duration = QuickstepAppTransitionManagerImpl.CONTENT_ALPHA_DURATION;
long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
if (mAnimator != null) {
mAnimator.cancel();
}
@@ -30,7 +30,6 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.content.Intent;
@@ -262,14 +261,13 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
RecentsView rv = getOverviewPanel();
TaskView tasktolaunch = rv.getTaskViewAt(0);
if (tasktolaunch != null) {
tasktolaunch.launchTask(false, success -> {
tasktolaunch.launchTask(success -> {
if (!success) {
getStateManager().goToState(OVERVIEW);
tasktolaunch.notifyTaskLaunchFailed(TAG);
} else {
getStateManager().moveToRestState();
}
}, MAIN_EXECUTOR.getHandler());
});
} else {
getStateManager().goToState(NORMAL);
}
@@ -155,7 +155,7 @@ public class OverviewState extends LauncherState {
public void onBackPressed(Launcher launcher) {
TaskView taskView = launcher.<RecentsView>getOverviewPanel().getRunningTaskView();
if (taskView != null) {
taskView.launchTask(true);
taskView.launchTaskAnimated();
} else {
super.onBackPressed(launcher);
}
@@ -22,7 +22,7 @@ import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -1624,19 +1624,17 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
mGestureState.updateLastStartedTaskId(taskId);
boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds()
.contains(taskId);
nextTask.launchTask(false /* animate */, true /* freezeTaskList */,
success -> {
resultCallback.accept(success);
if (success) {
if (hasTaskPreviouslyAppeared) {
onRestartPreviouslyAppearedTask();
}
} else {
mActivityInterface.onLaunchTaskFailed();
nextTask.notifyTaskLaunchFailed(TAG);
mRecentsAnimationController.finish(true /* toRecents */, null);
}
}, MAIN_EXECUTOR.getHandler());
nextTask.launchTask(success -> {
resultCallback.accept(success);
if (success) {
if (hasTaskPreviouslyAppeared) {
onRestartPreviouslyAppearedTask();
}
} else {
mActivityInterface.onLaunchTaskFailed();
mRecentsAnimationController.finish(true /* toRecents */, null);
}
}, true /* freezeTaskList */);
} else {
mActivityInterface.onLaunchTaskFailed();
Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show();
@@ -132,7 +132,7 @@ public class OverviewCommandHelper {
}
int currentPage = recents.getNextPage();
if (currentPage >= 0 && currentPage < recents.getTaskViewCount()) {
((TaskView) recents.getPageAt(currentPage)).launchTask(true);
((TaskView) recents.getPageAt(currentPage)).launchTaskAnimated();
} else {
recents.startHome();
}
@@ -18,9 +18,9 @@ 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.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.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
import static com.android.launcher3.Utilities.createHomeIntent;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
@@ -30,7 +30,6 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MOD
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.app.ActivityOptions;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -46,7 +45,6 @@ import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
import com.android.launcher3.R;
import com.android.launcher3.WrappedAnimationRunnerImpl;
import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
@@ -54,7 +52,9 @@ import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
@@ -94,7 +94,6 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
// Strong refs to runners which are cleared when the activity is destroyed
private WrappedAnimationRunnerImpl mActivityLaunchAnimationRunner;
private SearchAdapterProvider mSearchAdapterProvider;
/**
* Init drag layer and overview panel views.
@@ -172,42 +171,40 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
}
@Override
public ActivityOptions getActivityLaunchOptions(final View v) {
public ActivityOptionsWrapper getActivityLaunchOptions(final View v) {
if (!(v instanceof TaskView)) {
return null;
return super.getActivityLaunchOptions(v);
}
final TaskView taskView = (TaskView) v;
mActivityLaunchAnimationRunner = new WrappedAnimationRunnerImpl() {
@Override
public Handler getHandler() {
return mUiHandler;
}
RunnableList onEndCallback = new RunnableList();
@Override
public void onCreateAnimation(int transit,
mActivityLaunchAnimationRunner = (int transit,
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
RemoteAnimationTargetCompat[] nonAppTargets,
AnimationResult result) {
AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
wallpaperTargets);
anim.addListener(resetStateListener());
result.setAnimation(anim, RecentsActivity.this);
}
AnimationResult result) -> {
AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
wallpaperTargets);
anim.addListener(resetStateListener());
result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy);
};
final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner<>(
mActivityLaunchAnimationRunner, true /* startAtFrontOfQueue */);
return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
mUiHandler, mActivityLaunchAnimationRunner, true /* startAtFrontOfQueue */);
RemoteAnimationAdapterCompat adapterCompat = new RemoteAnimationAdapterCompat(
wrapper, RECENTS_LAUNCH_DURATION,
RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
- STATUS_BAR_TRANSITION_PRE_DELAY));
- STATUS_BAR_TRANSITION_PRE_DELAY);
return new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
onEndCallback);
}
/**
* Composes the animations for a launch from the recents list if possible.
*/
private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView,
private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView,
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets) {
AnimatorSet target = new AnimatorSet();
@@ -38,7 +38,6 @@ import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
import com.android.launcher3.model.WellbeingModel;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.popup.SystemShortcut.AppInfo;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.InstantAppResolver;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
@@ -54,7 +53,6 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
/**
* Represents a system shortcut that can be shown for a recent task.
@@ -281,15 +279,9 @@ public interface TaskShortcutFactory {
@Override
public void onClick(View view) {
Consumer<Boolean> resultCallback = success -> {
if (success) {
SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning(
mTaskView.getTask().key.id);
} else {
mTaskView.notifyTaskLaunchFailed(TAG);
}
};
mTaskView.launchTask(true, resultCallback, Executors.MAIN_EXECUTOR.getHandler());
if (mTaskView.launchTaskAnimated() != null) {
SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning(mTaskView.getTask().key.id);
}
dismissTaskMenuView(mTarget);
mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
.log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
@@ -18,7 +18,7 @@ package com.android.quickstep;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
@@ -21,7 +21,6 @@ import android.content.Context;
import android.os.Handler;
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
import com.android.launcher3.WrappedAnimationRunnerImpl;
import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.systemui.shared.system.ActivityOptionsCompat;
@@ -36,23 +35,10 @@ public abstract class RemoteAnimationProvider {
RemoteAnimationTargetCompat[] wallpaperTargets);
ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
mAnimationRunner = new WrappedAnimationRunnerImpl() {
@Override
public Handler getHandler() {
return handler;
}
@Override
public void onCreateAnimation(int transit,
RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
RemoteAnimationTargetCompat[] nonApps,
AnimationResult result) {
mAnimationRunner = (transit, appTargets, wallpaperTargets, nonApps, result) ->
result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
}
};
final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner(
mAnimationRunner, false /* startAtFrontOfQueue */);
handler, mAnimationRunner, false /* startAtFrontOfQueue */);
return ActivityOptionsCompat.makeRemoteAnimation(
new RemoteAnimationAdapterCompat(wrapper, duration, 0));
}
@@ -21,7 +21,7 @@ import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.QuickstepTransitionManager.ALL_APPS_PROGRESS_OFF_SCREEN;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
@@ -1467,7 +1467,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
}
}
targetTask.setEndQuickswitchCuj(true);
targetTask.launchTask(true);
targetTask.launchTaskAnimated();
}
public void setRunningTaskIconScaledDown(boolean isScaledDown) {
@@ -2494,17 +2494,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
}
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
Consumer<Boolean> onLaunchResult = (result) -> {
onTaskLaunchAnimationEnd(result);
if (!result) {
tv.notifyTaskLaunchFailed(TAG);
}
};
if (LIVE_TILE.get()) {
finishRecentsAnimation(false /* toRecents */, null);
onLaunchResult.accept(true /* success */);
onTaskLaunchAnimationEnd(true /* success */);
} else {
tv.launchTask(false, onLaunchResult, getHandler());
tv.launchTask(this::onTaskLaunchAnimationEnd);
}
Task task = tv.getTask();
if (task != null) {
@@ -27,7 +27,7 @@ import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.widget.Toast.LENGTH_SHORT;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.Utilities.comp;
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
@@ -37,6 +37,7 @@ import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
@@ -52,7 +53,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
@@ -66,6 +66,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
@@ -79,7 +81,9 @@ import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.TransformingTouchDelegate;
import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
@@ -335,7 +339,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
});
anim.start();
} else {
launchTask(true /* animate */);
launchTaskAnimated();
}
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_TAP);
@@ -483,63 +487,62 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
.createPlaybackController();
}
public void launchTask(boolean animate) {
launchTask(animate, false /* freezeTaskList */);
}
public void launchTask(boolean animate, boolean freezeTaskList) {
launchTask(animate, freezeTaskList, (result) -> {
if (!result) {
notifyTaskLaunchFailed(TAG);
}
}, getHandler());
}
public void launchTask(boolean animate, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
launchTask(animate, false /* freezeTaskList */, resultCallback, resultCallbackHandler);
}
public void launchTask(boolean animate, boolean freezeTaskList, Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
/**
* Starts the task associated with this view and animates the startup.
* @return CompletionStage to indicate the animation completion or null if the launch failed.
*/
public RunnableList launchTaskAnimated() {
if (mTask != null) {
final ActivityOptions opts;
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
if (animate) {
opts = mActivity.getActivityLaunchOptions(this);
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
opts, resultCallback, resultCallbackHandler);
ActivityOptionsWrapper opts = mActivity.getActivityLaunchOptions(this);
if (ActivityManagerWrapper.getInstance()
.startActivityFromRecents(mTask.key, opts.options)) {
return opts.onEndCallback;
} else {
opts = ActivityOptionsCompat.makeCustomAnimation(getContext(), 0, 0, () -> {
if (resultCallback != null) {
// Only post the animation start after the system has indicated that the
// transition has started
resultCallbackHandler.post(() -> resultCallback.accept(true));
}
}, resultCallbackHandler);
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
UI_HELPER_EXECUTOR.execute(
() -> ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(
mTask.key,
opts,
(success) -> {
if (resultCallback != null && !success) {
// If the call to start activity failed, then post the
// result
// immediately, otherwise, wait for the animation start
// callback
// from the activity options above
resultCallbackHandler.post(
() -> resultCallback.accept(false));
}
}, resultCallbackHandler));
notifyTaskLaunchFailed(TAG);
return null;
}
} else {
return null;
}
}
/**
* Starts the task associated with this view without any animation
*/
public void launchTask(@NonNull Consumer<Boolean> callback) {
launchTask(callback, false /* freezeTaskList */);
}
/**
* Starts the task associated with this view without any animation
*/
public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
if (mTask != null) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
// Indicate success once the system has indicated that the transition has started
ActivityOptions opts = ActivityOptionsCompat.makeCustomAnimation(
getContext(), 0, 0, () -> callback.accept(true), MAIN_EXECUTOR.getHandler());
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
Task.TaskKey key = mTask.key;
UI_HELPER_EXECUTOR.execute(() -> {
if (!ActivityManagerWrapper.getInstance().startActivityFromRecents(key, opts)) {
// If the call to start activity failed, then post the result immediately,
// otherwise, wait for the animation start callback from the activity options
// above
MAIN_EXECUTOR.post(() -> {
notifyTaskLaunchFailed(TAG);
callback.accept(false);
});
}
});
} else {
callback.accept(false);
}
}
@@ -1123,7 +1126,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
return getRecentsView().mOrientationState.getOrientationHandler();
}
public void notifyTaskLaunchFailed(String tag) {
private void notifyTaskLaunchFailed(String tag) {
String msg = "Failed to launch task";
if (mTask != null) {
msg += " (task=" + mTask.key.baseIntent + " userId=" + mTask.key.userId + ")";
-1
View File
@@ -61,7 +61,6 @@
<!-- Various classes overriden by projects/build flavors. -->
<string name="folder_name_provider_class" translatable="false"></string>
<string name="stats_log_manager_class" translatable="false"></string>
<string name="app_transition_manager_class" translatable="false"></string>
<string name="instant_app_resolver_class" translatable="false"></string>
<string name="main_process_initializer_class" translatable="false"></string>
<string name="app_launch_tracker_class" translatable="false"></string>
+1 -1
View File
@@ -279,7 +279,7 @@ public abstract class BaseActivity extends Activity implements ActivityContext {
/**
* Used to set the override visibility state, used only to handle the transition home with the
* recents animation.
* @see QuickstepAppTransitionManagerImpl#createWallpaperOpenRunner
* @see QuickstepTransitionManager#createWallpaperOpenRunner
*/
public void addForceInvisibleFlag(@InvisibilityFlags int flag) {
mForceInvisible |= flag;
@@ -27,6 +27,7 @@ import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Process;
import android.os.StrictMode;
@@ -40,6 +41,7 @@ import android.view.WindowInsets.Type;
import android.view.WindowMetrics;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -52,10 +54,12 @@ import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.WindowBounds;
@@ -76,6 +80,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
protected boolean mIsSafeModeEnabled;
private Runnable mOnStartCallback;
private RunnableList mOnResumeCallbacks = new RunnableList();
private int mThemeRes = R.style.AppTheme;
@@ -97,6 +102,16 @@ public abstract class BaseDraggingActivity extends BaseActivity
}
}
@Override
protected void onResume() {
super.onResume();
mOnResumeCallbacks.executeAllAndClear();
}
public void addOnResumeCallback(Runnable callback) {
mOnResumeCallbacks.add(callback);
}
@Override
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
updateTheme();
@@ -149,20 +164,35 @@ public abstract class BaseDraggingActivity extends BaseActivity
return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
}
public final Bundle getActivityLaunchOptionsAsBundle(View v) {
ActivityOptions activityOptions = getActivityLaunchOptions(v);
return activityOptions == null ? null : activityOptions.toBundle();
@NonNull
public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
int left = 0, top = 0;
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
if (v instanceof BubbleTextView) {
// Launch from center of icon, not entire view
Drawable icon = ((BubbleTextView) v).getIcon();
if (icon != null) {
Rect bounds = icon.getBounds();
left = (width - bounds.width()) / 2;
top = v.getPaddingTop();
width = bounds.width();
height = bounds.height();
}
}
ActivityOptions options =
ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
RunnableList callback = new RunnableList();
addOnResumeCallback(callback::executeAllAndDestroy);
return new ActivityOptionsWrapper(options, callback);
}
public abstract ActivityOptions getActivityLaunchOptions(View v);
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false;
}
Bundle optsBundle = (v != null) ? getActivityLaunchOptionsAsBundle(v) : null;
Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v).toBundle() : null;
UserHandle user = item == null ? null : item.user;
// Prepare intent
@@ -50,7 +50,6 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.DotInfo;
@@ -81,7 +80,7 @@ import java.text.NumberFormat;
* because we want to make the bubble taller than the text and TextView's clip is
* too aggressive.
*/
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback,
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
IconLabelDotView, DraggableView, Reorderable {
private static final int DISPLAY_WORKSPACE = 0;
@@ -431,13 +430,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
}
}
@Override
public void onLauncherResume() {
// Reset the pressed state of icon that was locked in the press state while activity
// was launching
setStayPressed(false);
}
void clearPressedBackground() {
setPressed(false);
setStayPressed(false);
+5 -41
View File
@@ -61,7 +61,6 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
import android.content.ActivityNotFoundException;
@@ -276,7 +275,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
private static final int THEME_CROSS_FADE_ANIMATION_DURATION = 375;
private LauncherAppTransitionManager mAppTransitionManager;
private Configuration mOldConfig;
private LiveSearchManager mLiveSearchManager;
@@ -312,8 +310,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
@Thunk
boolean mWorkspaceLoading = true;
private ArrayList<OnResumeCallback> mOnResumeCallbacks = new ArrayList<>();
// Used to notify when an activity launch has been deferred because launcher is not yet resumed
// TODO: See if we can remove this later
private Runnable mOnDeferredActivityLaunchCallback;
@@ -419,9 +415,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
crossFadeWithPreviousAppearance();
mPopupDataProvider = new PopupDataProvider(this::updateNotificationDots);
mAppTransitionManager = LauncherAppTransitionManager.newInstance(this);
mAppTransitionManager.registerRemoteAnimations();
boolean internalStateHandled = ACTIVITY_TRACKER.handleCreate(this);
if (internalStateHandled) {
if (savedInstanceState != null) {
@@ -1090,15 +1083,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
TraceHelper.FLAG_UI_EVENT);
super.onResume();
if (!mOnResumeCallbacks.isEmpty()) {
final ArrayList<OnResumeCallback> resumeCallbacks = new ArrayList<>(mOnResumeCallbacks);
mOnResumeCallbacks.clear();
for (int i = resumeCallbacks.size() - 1; i >= 0; i--) {
resumeCallbacks.get(i).onLauncherResume();
}
resumeCallbacks.clear();
}
if (mDeferOverlayCallbacks) {
scheduleDeferredCheck();
} else {
@@ -1609,7 +1593,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
LauncherAppState.getIDP(this).removeOnChangeListener(this);
mOverlayManager.onActivityDestroyed(this);
mAppTransitionManager.onActivityDestroyed();
mUserChangedCallbackCloseable.close();
mLiveSearchManager.stop();
}
@@ -1933,16 +1916,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
}
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public ActivityOptions getActivityLaunchOptions(View v) {
return mAppTransitionManager.getActivityLaunchOptions(this, v);
}
public LauncherAppTransitionManager getAppTransitionManager() {
return mAppTransitionManager;
}
@TargetApi(Build.VERSION_CODES.M)
@Override
protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) {
@@ -1993,7 +1966,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
// state when we return to launcher.
BubbleTextView btv = (BubbleTextView) v;
btv.setStayPressed(true);
addOnResumeCallback(btv);
addOnResumeCallback(() -> btv.setStayPressed(false));
}
return success;
}
@@ -2037,10 +2010,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
return result;
}
public void addOnResumeCallback(OnResumeCallback callback) {
mOnResumeCallbacks.add(callback);
}
/**
* Persistant callback which notifies when an activity launch is deferred because the activity
* was not yet resumed.
@@ -2814,15 +2783,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
return (T) activityContext;
}
/**
* Callback for listening for onResume
*/
public interface OnResumeCallback {
void onLauncherResume();
}
/**
* Cross-fades the launcher's updated appearance with its previous appearance.
*
@@ -2865,6 +2825,10 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
return false;
}
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return false;
}
public DragOptions getDefaultWorkspaceDragOptions() {
return new DragOptions();
}
@@ -1,91 +0,0 @@
/*
* 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 android.app.ActivityOptions;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
import com.android.launcher3.util.ResourceBasedOverride;
/**
* Manages the opening and closing app transitions from Launcher.
*/
public class LauncherAppTransitionManager implements ResourceBasedOverride {
public static LauncherAppTransitionManager newInstance(Context context) {
return Overrides.getObject(LauncherAppTransitionManager.class,
context, R.string.app_transition_manager_class);
}
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
int left = 0, top = 0;
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
if (v instanceof BubbleTextView) {
// Launch from center of icon, not entire view
Drawable icon = ((BubbleTextView) v).getIcon();
if (icon != null) {
Rect bounds = icon.getBounds();
left = (width - bounds.width()) / 2;
top = v.getPaddingTop();
width = bounds.width();
height = bounds.height();
}
}
return ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
}
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return false;
}
/**
* Registers remote animations for certain system transitions.
*/
public void registerRemoteAnimations() {
// Do nothing
}
/**
* Handles clean up when activity is destroyed.
*/
public void onActivityDestroyed() {
// Do nothing
}
/**
* Unregisters all remote animations.
*/
public void unregisterRemoteAnimations() {
// Do nothing
}
/**
* Registers remote transitions for certain system transitions.
*/
public void registerRemoteTransitions() {
// Do nothing
}
/**
* Unregisters all remote transitions.
*/
public void unregisterRemoteTransitions() {
// Do nothing
}
}
@@ -33,7 +33,6 @@ import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.logging.FileLog;
@@ -228,7 +227,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
if (target != null) {
deferred.mPackageName = target.getPackageName();
mLauncher.addOnResumeCallback(deferred);
mLauncher.addOnResumeCallback(deferred::onLauncherResume);
} else {
deferred.sendFailure();
}
@@ -311,7 +310,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
* A wrapper around {@link DragSource} which delays the {@link #onDropCompleted} action until
* {@link #onLauncherResume}
*/
private class DeferredOnComplete implements DragSource, OnResumeCallback {
private class DeferredOnComplete implements DragSource {
private final DragSource mOriginal;
private final Context mContext;
@@ -330,7 +329,6 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
mDragObject = d;
}
@Override
public void onLauncherResume() {
// We use MATCH_UNINSTALLED_PACKAGES as the app can be on SD card as well.
if (new PackageManagerHelper(mContext).getApplicationInfo(mPackageName,
@@ -17,7 +17,6 @@ package com.android.launcher3.secondarydisplay;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
@@ -167,11 +166,6 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
return mDragLayer;
}
@Override
public ActivityOptions getActivityLaunchOptions(View v) {
return null;
}
@Override
protected void reapplyUi() { }
@@ -180,7 +180,7 @@ public class ItemClickHandler {
LauncherApps launcherApps = launcher.getSystemService(LauncherApps.class);
try {
launcherApps.startPackageInstallerSessionDetailsActivity(sessionInfo, null,
launcher.getActivityLaunchOptionsAsBundle(v));
launcher.getActivityLaunchOptions(v).toBundle());
return;
} catch (Exception e) {
Log.e(TAG, "Unable to launch market intent for package=" + packageName, e);
@@ -304,7 +304,7 @@ public class ItemClickHandler {
intent.setPackage(null);
}
}
if (v != null && launcher.getAppTransitionManager().supportsAdaptiveIconAnimation(v)) {
if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
// Preload the icon to reduce latency b/w swapping the floating view with the original.
FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
}
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2021 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.util;
import android.app.ActivityOptions;
import android.os.Bundle;
/**
* A wrapper around {@link ActivityOptions} to allow custom functionality in launcher
*/
public class ActivityOptionsWrapper {
public final ActivityOptions options;
public final RunnableList onEndCallback;
public ActivityOptionsWrapper(ActivityOptions options, RunnableList onEndCallback) {
this.options = options;
this.onEndCallback = onEndCallback;
}
/**
* @see {@link ActivityOptions#toBundle()}
*/
public Bundle toBundle() {
return options.toBundle();
}
}
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2021 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.util;
import java.util.ArrayList;
/**
* Utility class to hold a list of runnable
*/
public class RunnableList {
private ArrayList<Runnable> mList = null;
private boolean mDestroyed = false;
/**
* Ads a runnable to this list
*/
public void add(Runnable runnable) {
if (mDestroyed) {
runnable.run();
return;
}
if (mList == null) {
mList = new ArrayList<>();
}
mList.add(runnable);
}
/**
* Destroys the list, executing any pending callbacks. All new callbacks are
* immediately executed
*/
public void executeAllAndDestroy() {
mDestroyed = true;
executeAllAndClear();
}
/**
* Executes all previously added runnable and clears the list
*/
public void executeAllAndClear() {
if (mList != null) {
ArrayList<Runnable> list = mList;
mList = null;
int count = list.size();
for (int i = 0; i < count; i++) {
list.get(i).run();
}
}
}
}