Several app transition fixes:
> If launcher already started, creating the state transition only after threshold crossed, so that previous animations are not cancelled
> Not posting animaiton callbacks at the front of the queue, as that sometimes causes it get executed before onNewIntent
> Farking the activity as forceInvisible while launching an opaque app, so that quickly pressing home/back runs the reverse animation
> Not running state animations when force-invisible is true
Bug: 77830325
Bug: 77898806
Change-Id: I50a7e915ca35fd6aeb284c8f321ecca74396fe98
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index f919339..cd67300 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -15,9 +15,6 @@
*/
package com.android.launcher3;
-import static com.android.systemui.shared.recents.utilities.Utilities
- .postAtFrontOfQueueAsynchronously;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -49,7 +46,7 @@
@BinderThread
@Override
public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats, Runnable runnable) {
- postAtFrontOfQueueAsynchronously(mHandler, () -> {
+ mHandler.post(() -> {
// Finish any previous animation
finishSystemAnimation();
@@ -68,7 +65,6 @@
});
}
-
@UiThread
public abstract AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats);
@@ -87,7 +83,7 @@
@BinderThread
@Override
public void onAnimationCancelled() {
- postAtFrontOfQueueAsynchronously(mHandler, () -> {
+ mHandler.post(() -> {
if (mAnimator != null) {
mAnimator.removeListener(this);
mAnimator.end();
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 1620352..299e7d5 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
+import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
@@ -119,6 +121,18 @@
}
};
+ private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mLauncher.addForceInvisibleFlag(INVISIBLE_BY_APP_TRANSITIONS);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLauncher.clearForceInvisibleFlag(INVISIBLE_BY_APP_TRANSITIONS);
+ }
+ };
+
public LauncherAppTransitionManagerImpl(Context context) {
mLauncher = Launcher.getLauncher(context);
mDragLayer = mLauncher.getDragLayer();
@@ -126,7 +140,6 @@
mIsRtl = Utilities.isRtl(mLauncher.getResources());
mDeviceProfile = mLauncher.getDeviceProfile();
-
Resources res = mLauncher.getResources();
mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
@@ -147,38 +160,40 @@
@Override
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
if (hasControlRemoteAppTransitionPermission()) {
- try {
- RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler) {
+ RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler) {
- @Override
- public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
- AnimatorSet anim = new AnimatorSet();
+ @Override
+ public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
+ AnimatorSet anim = new AnimatorSet();
+ 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);
+ 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);
- anim.play(getIconAnimator(v));
- if (launcherIsATargetWithMode(targetCompats, MODE_CLOSING)) {
- anim.play(getLauncherContentAnimator(false /* show */));
- }
- anim.play(getWindowAnimators(v, targetCompats));
+ anim.play(getIconAnimator(v));
+ if (launcherClosing) {
+ anim.play(getLauncherContentAnimator(false /* show */));
}
- return anim;
+ anim.play(getWindowAnimators(v, targetCompats));
}
- };
- int duration = findTaskViewToLaunch(launcher, v, null) != null
- ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION;
- int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION;
- return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
- runner, duration, statusBarTransitionDelay));
- } catch (NoClassDefFoundError e) {
- // Gracefully fall back to default launch options if the user's platform doesn't
- // have the latest changes.
- }
+ if (launcherClosing) {
+ anim.addListener(mForceInvisibleListener);
+ }
+
+ return anim;
+ }
+ };
+
+ int duration = findTaskViewToLaunch(launcher, v, null) != null
+ ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION;
+ int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION;
+ return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
+ runner, duration, statusBarTransitionDelay));
}
return getDefaultActivityLaunchOptions(launcher, v);
}
@@ -521,19 +536,14 @@
private void registerRemoteAnimations() {
// Unregister this
if (hasControlRemoteAppTransitionPermission()) {
- try {
- RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
- definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
- WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
- new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(),
- CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
+ RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
+ definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
+ WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
+ new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(),
+ CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
-// TODO: App controlled transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
-
- new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
- } catch (NoClassDefFoundError e) {
- // Gracefully fall back if the user's platform doesn't have the latest changes
- }
+ // TODO: Transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
+ new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
}
}
@@ -575,7 +585,7 @@
}
}
- mLauncher.setForceInvisible(false);
+ mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
return anim;
}
};
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 1255a02..ce16adf 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -15,6 +15,7 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_DURATION;
@@ -38,6 +39,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
+import android.support.annotation.AnyThread;
import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread;
import android.util.Log;
@@ -46,6 +48,7 @@
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
@@ -208,7 +211,7 @@
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
this::launcherFrameDrawn);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
- this::notifyGestureStarted);
+ this::onGestureStartedWithLauncher);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
| STATE_GESTURE_CANCELLED,
this::resetStateForAnimationCancel);
@@ -290,7 +293,11 @@
mActivity = activity;
// Override the visibility of the activity until the gesture actually starts and we swipe
// up, or until we transition home and the home animation is composed
- mActivity.setForceInvisible(true);
+ if (alreadyOnHome) {
+ mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ } else {
+ mActivity.addForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+ }
mRecentsView = activity.getOverviewPanel();
mQuickScrubController = mRecentsView.getQuickScrubController();
@@ -317,11 +324,6 @@
AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible);
if (mWasLauncherAlreadyVisible) {
- mLauncherTransitionController = mActivityControlHelper
- .createControllerForVisibleActivity(activity);
- mLauncherTransitionController.dispatchOnStart();
- mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
-
mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
} else {
TraceHelper.beginSection("WTS-init");
@@ -420,6 +422,7 @@
if (!mWasLauncherAlreadyVisible) {
mLauncherTransitionController = mActivityControlHelper
.createControllerForHiddenActivity(mActivity, mTransitionDragLength);
+ mLauncherTransitionController.dispatchOnStart();
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
}
}
@@ -515,7 +518,7 @@
}
public void onGestureStarted() {
- notifyGestureStarted();
+ notifyGestureStartedAsync();
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
mRecentsAnimationWrapper.enableInputConsumer();
@@ -527,17 +530,29 @@
* Notifies the launcher that the swipe gesture has started. This can be called multiple times
* on both background and UI threads
*/
- private void notifyGestureStarted() {
+ @AnyThread
+ private void notifyGestureStartedAsync() {
final T curActivity = mActivity;
if (curActivity != null) {
// Once the gesture starts, we can no longer transition home through the button, so
// reset the force override of the activity visibility
- mActivity.setForceInvisible(false);
+ mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
mActivityControlHelper.onQuickstepGestureStarted(
curActivity, mWasLauncherAlreadyVisible);
}
}
+ private void onGestureStartedWithLauncher() {
+ notifyGestureStartedAsync();
+
+ if (mWasLauncherAlreadyVisible) {
+ mLauncherTransitionController = mActivityControlHelper
+ .createControllerForVisibleActivity(mActivity);
+ mLauncherTransitionController.dispatchOnStart();
+ mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
+ }
+ }
+
@WorkerThread
public void onGestureEnded(float endVelocity) {
Resources res = mContext.getResources();
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index c15cde5..1f1ef9a 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -16,12 +16,15 @@
package com.android.launcher3;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Point;
+import android.support.annotation.IntDef;
import android.view.Display;
import android.view.View.AccessibilityDelegate;
@@ -29,10 +32,22 @@
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.util.SystemUiController;
+import java.lang.annotation.Retention;
import java.util.ArrayList;
public abstract class BaseActivity extends Activity {
+ public static final int INVISIBLE_BY_STATE_HANDLER = 1 << 0;
+ public static final int INVISIBLE_BY_APP_TRANSITIONS = 1 << 1;
+ public static final int INVISIBLE_ALL =
+ INVISIBLE_BY_STATE_HANDLER | INVISIBLE_BY_APP_TRANSITIONS;
+
+ @Retention(SOURCE)
+ @IntDef(
+ flag = true,
+ value = {INVISIBLE_BY_STATE_HANDLER, INVISIBLE_BY_APP_TRANSITIONS})
+ public @interface InvisibilityFlags{}
+
private final ArrayList<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
private final ArrayList<MultiWindowModeChangedListener> mMultiWindowModeChangedListeners =
new ArrayList<>();
@@ -42,10 +57,11 @@
protected SystemUiController mSystemUiController;
private boolean mStarted;
+ private boolean mUserActive;
+
// When the recents animation is running, the visibility of the Launcher is managed by the
// animation
- private boolean mForceInvisible;
- private boolean mUserActive;
+ @InvisibilityFlags private int mForceInvisible;
public DeviceProfile getDeviceProfile() {
return mDeviceProfile;
@@ -114,7 +130,7 @@
@Override
protected void onStop() {
mStarted = false;
- mForceInvisible = false;
+ mForceInvisible = 0;
super.onStop();
}
@@ -153,15 +169,20 @@
* recents animation.
* @see LauncherAppTransitionManagerImpl.getWallpaperOpenRunner()
*/
- public void setForceInvisible(boolean invisible) {
- mForceInvisible = invisible;
+ public void addForceInvisibleFlag(@InvisibilityFlags int flag) {
+ mForceInvisible |= flag;
}
+ public void clearForceInvisibleFlag(@InvisibilityFlags int flag) {
+ mForceInvisible &= ~flag;
+ }
+
+
/**
* @return Wether this activity should be considered invisible regardless of actual visibility.
*/
public boolean isForceInvisible() {
- return mForceInvisible;
+ return mForceInvisible != 0;
}
/**
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index d5e6a9d..01166a1 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -121,7 +121,7 @@
* @see #goToState(LauncherState, boolean, Runnable)
*/
public void goToState(LauncherState state) {
- goToState(state, mLauncher.isStarted() /* animated */, 0, null);
+ goToState(state, !mLauncher.isForceInvisible() && mLauncher.isStarted() /* animated */);
}
/**