Merge "Add support for the no-animation intent option"
This commit is contained in:
@@ -141,8 +141,11 @@ public final class TransitionInfo implements Parcelable {
|
||||
/** The window was animated by back gesture. */
|
||||
public static final int FLAG_BACK_GESTURE_ANIMATED = 1 << 17;
|
||||
|
||||
/** The window should have no animation (by policy). */
|
||||
public static final int FLAG_NO_ANIMATION = 1 << 18;
|
||||
|
||||
/** The first unused bit. This can be used by remotes to attach custom flags to this change. */
|
||||
public static final int FLAG_FIRST_CUSTOM = 1 << 18;
|
||||
public static final int FLAG_FIRST_CUSTOM = 1 << 19;
|
||||
|
||||
/** The change belongs to a window that won't contain activities. */
|
||||
public static final int FLAGS_IS_NON_APP_WINDOW =
|
||||
@@ -169,6 +172,7 @@ public final class TransitionInfo implements Parcelable {
|
||||
FLAG_IS_OCCLUDED,
|
||||
FLAG_IS_SYSTEM_WINDOW,
|
||||
FLAG_BACK_GESTURE_ANIMATED,
|
||||
FLAG_NO_ANIMATION,
|
||||
FLAG_FIRST_CUSTOM
|
||||
})
|
||||
public @interface ChangeFlags {}
|
||||
@@ -387,6 +391,9 @@ public final class TransitionInfo implements Parcelable {
|
||||
if ((flags & FLAG_BACK_GESTURE_ANIMATED) != 0) {
|
||||
sb.append(sb.length() == 0 ? "" : "|").append("FLAG_BACK_GESTURE_ANIMATED");
|
||||
}
|
||||
if ((flags & FLAG_NO_ANIMATION) != 0) {
|
||||
sb.append(sb.length() == 0 ? "" : "|").append("NO_ANIMATION");
|
||||
}
|
||||
if ((flags & FLAG_FIRST_CUSTOM) != 0) {
|
||||
sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM");
|
||||
}
|
||||
|
||||
@@ -301,6 +301,14 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if no-animation and skip animation if so.
|
||||
if (Transitions.isAllNoAnimation(info)) {
|
||||
startTransaction.apply();
|
||||
finishTransaction.apply();
|
||||
finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAnimations.containsKey(transition)) {
|
||||
throw new IllegalStateException("Got a duplicate startAnimation call for "
|
||||
+ transition);
|
||||
|
||||
@@ -26,6 +26,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
import static android.view.WindowManager.fixScale;
|
||||
import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
|
||||
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
|
||||
import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
|
||||
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
|
||||
|
||||
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
|
||||
@@ -448,6 +449,34 @@ public class Transitions implements RemoteCallable<Transitions> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look through a transition and see if all non-closing changes are no-animation. If so, no
|
||||
* animation should play.
|
||||
*/
|
||||
static boolean isAllNoAnimation(TransitionInfo info) {
|
||||
if (isClosingType(info.getType())) {
|
||||
// no-animation is only relevant for launching (open) activities.
|
||||
return false;
|
||||
}
|
||||
boolean hasNoAnimation = false;
|
||||
final int changeSize = info.getChanges().size();
|
||||
for (int i = changeSize - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (isClosingType(change.getMode())) {
|
||||
// ignore closing apps since they are a side-effect of the transition and don't
|
||||
// animate.
|
||||
continue;
|
||||
}
|
||||
if (change.hasFlags(FLAG_NO_ANIMATION)) {
|
||||
hasNoAnimation = true;
|
||||
} else {
|
||||
// at-least one relevant participant *is* animated, so we need to animate.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return hasNoAnimation;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl.Transaction finishT) {
|
||||
|
||||
@@ -5029,10 +5029,10 @@ class Task extends TaskFragment {
|
||||
final DisplayContent dc = mDisplayContent;
|
||||
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
|
||||
"Prepare open transition: starting " + r);
|
||||
// TODO(shell-transitions): record NO_ANIMATION flag somewhere.
|
||||
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
|
||||
dc.prepareAppTransition(TRANSIT_NONE);
|
||||
mTaskSupervisor.mNoAnimActivities.add(r);
|
||||
mTransitionController.setNoAnimation(r);
|
||||
} else {
|
||||
dc.prepareAppTransition(TRANSIT_OPEN);
|
||||
mTaskSupervisor.mNoAnimActivities.remove(r);
|
||||
|
||||
@@ -47,6 +47,7 @@ import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
|
||||
import static android.window.TransitionInfo.FLAG_IS_INPUT_METHOD;
|
||||
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
|
||||
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
|
||||
import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
|
||||
import static android.window.TransitionInfo.FLAG_OCCLUDES_KEYGUARD;
|
||||
import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER;
|
||||
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
|
||||
@@ -916,6 +917,14 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
||||
return mRemoteTransition;
|
||||
}
|
||||
|
||||
void setNoAnimation(WindowContainer wc) {
|
||||
final ChangeInfo change = mChanges.get(wc);
|
||||
if (change == null) {
|
||||
throw new IllegalStateException("Can't set no-animation property of non-participant");
|
||||
}
|
||||
change.mFlags |= ChangeInfo.FLAG_CHANGE_NO_ANIMATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
|
||||
if (syncId != mSyncId) {
|
||||
@@ -1442,6 +1451,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
||||
i++;
|
||||
targets.add(parent);
|
||||
}
|
||||
if ((changes.get(target).mFlags & ChangeInfo.FLAG_CHANGE_NO_ANIMATION) != 0) {
|
||||
changes.get(parent).mFlags |= ChangeInfo.FLAG_CHANGE_NO_ANIMATION;
|
||||
} else {
|
||||
changes.get(parent).mFlags |= ChangeInfo.FLAG_CHANGE_YES_ANIMATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1880,11 +1894,21 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
||||
private static final int FLAG_TRANSIENT_LAUNCH = 2;
|
||||
private static final int FLAG_ABOVE_TRANSIENT_LAUNCH = 4;
|
||||
|
||||
/** This container explicitly requested no-animation (usually Activity level). */
|
||||
private static final int FLAG_CHANGE_NO_ANIMATION = 0x8;
|
||||
/**
|
||||
* This container has at-least one child which IS animating (not marked NO_ANIMATION).
|
||||
* Used during promotion. This trumps `FLAG_NO_ANIMATION` (if both are set).
|
||||
*/
|
||||
private static final int FLAG_CHANGE_YES_ANIMATION = 0x10;
|
||||
|
||||
@IntDef(prefix = { "FLAG_" }, value = {
|
||||
FLAG_NONE,
|
||||
FLAG_SEAMLESS_ROTATION,
|
||||
FLAG_TRANSIENT_LAUNCH,
|
||||
FLAG_ABOVE_TRANSIENT_LAUNCH
|
||||
FLAG_ABOVE_TRANSIENT_LAUNCH,
|
||||
FLAG_CHANGE_NO_ANIMATION,
|
||||
FLAG_CHANGE_YES_ANIMATION
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface Flag {}
|
||||
@@ -2055,6 +2079,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
||||
if (occludesKeyguard(wc)) {
|
||||
flags |= FLAG_OCCLUDES_KEYGUARD;
|
||||
}
|
||||
if ((mFlags & FLAG_CHANGE_NO_ANIMATION) != 0
|
||||
&& (mFlags & FLAG_CHANGE_YES_ANIMATION) == 0) {
|
||||
flags |= FLAG_NO_ANIMATION;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -561,6 +561,11 @@ class TransitionController {
|
||||
mCollectingTransition.setOverrideAnimation(options, startCallback, finishCallback);
|
||||
}
|
||||
|
||||
void setNoAnimation(WindowContainer wc) {
|
||||
if (mCollectingTransition == null) return;
|
||||
mCollectingTransition.setNoAnimation(wc);
|
||||
}
|
||||
|
||||
/** @see Transition#setReady */
|
||||
void setReady(WindowContainer wc, boolean ready) {
|
||||
if (mCollectingTransition == null) return;
|
||||
|
||||
@@ -462,6 +462,53 @@ public class TransitionTests extends WindowTestsBase {
|
||||
assertTrue(targets.contains(topTask));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInfo_NoAnimation() {
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task newTask = createTask(mDisplayContent);
|
||||
final Task oldTask = createTask(mDisplayContent);
|
||||
final ActivityRecord closing = createActivityRecord(oldTask);
|
||||
final ActivityRecord opening = createActivityRecord(newTask);
|
||||
// Start states.
|
||||
changes.put(newTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */));
|
||||
changes.put(oldTask, new Transition.ChangeInfo(true /* vis */, true /* exChg */));
|
||||
changes.put(opening, new Transition.ChangeInfo(false /* vis */, true /* exChg */));
|
||||
changes.put(closing, new Transition.ChangeInfo(true /* vis */, true /* exChg */));
|
||||
transition.setNoAnimation(opening);
|
||||
fillChangeMap(changes, newTask);
|
||||
// End states.
|
||||
closing.setVisibleRequested(false);
|
||||
opening.setVisibleRequested(true);
|
||||
|
||||
final int transit = transition.mType;
|
||||
int flags = 0;
|
||||
|
||||
// Check that no-animation flag is promoted
|
||||
participants.add(oldTask);
|
||||
participants.add(newTask);
|
||||
participants.add(opening);
|
||||
participants.add(closing);
|
||||
ArrayList<WindowContainer> targets = Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes,
|
||||
mMockT);
|
||||
assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken()));
|
||||
assertTrue(info.getChange(newTask.mRemoteToken.toWindowContainerToken())
|
||||
.hasFlags(TransitionInfo.FLAG_NO_ANIMATION));
|
||||
|
||||
// Check that no-animation flag is NOT promoted if at-least on child *is* animated
|
||||
final ActivityRecord opening2 = createActivityRecord(newTask);
|
||||
changes.put(opening2, new Transition.ChangeInfo(false /* vis */, true /* exChg */));
|
||||
participants.add(opening2);
|
||||
targets = Transition.calculateTargets(participants, changes);
|
||||
info = Transition.calculateTransitionInfo(transit, flags, targets, changes, mMockT);
|
||||
assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken()));
|
||||
assertFalse(info.getChange(newTask.mRemoteToken.toWindowContainerToken())
|
||||
.hasFlags(TransitionInfo.FLAG_NO_ANIMATION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargets_noIntermediatesToWallpaper() {
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
|
||||
Reference in New Issue
Block a user